From 02f4be4b5973e0621b1302fda58ee01e57e40db5 Mon Sep 17 00:00:00 2001 From: seteiro Date: Mon, 2 Nov 2026 15:23:08 +0800 Subject: [PATCH] drivers/ipc: harden pipe ioctl user pointer copy FIONREAD/FIONWRITE wrote through a raw user pointer in kernel mode. Compute into a stack int and lwp_put_to_user under RT_USING_LWP; keep direct write otherwise. Also null-check pipe/fifo. Fixes #11958. --- components/drivers/ipc/pipe.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/components/drivers/ipc/pipe.c b/components/drivers/ipc/pipe.c index 7471d5580772..e1e32af9797c 100644 --- a/components/drivers/ipc/pipe.c +++ b/components/drivers/ipc/pipe.c @@ -10,6 +10,7 @@ * 2023-06-28 shell return POLLHUP when writer closed its channel on poll() * fix flag test on pipe_fops_open() * 2023-12-02 shell Make read pipe operation interruptable. + * 2026-11-02 seteiro pipe ioctl: copy FIONREAD/FIONWRITE via lwp_put_to_user */ #include #include @@ -24,6 +25,9 @@ #include #include #include +#ifdef RT_USING_LWP +#include +#endif /* check RT_UNAMED_PIPE_NUMBER */ @@ -190,7 +194,7 @@ static int pipe_fops_ioctl(struct dfs_file *fd, int cmd, void *args) pipe = (rt_pipe_t *)fd->vnode->data; - if (args == RT_NULL) + if (args == RT_NULL || pipe == RT_NULL || pipe->fifo == RT_NULL) { return -EINVAL; } @@ -198,11 +202,25 @@ static int pipe_fops_ioctl(struct dfs_file *fd, int cmd, void *args) switch ((rt_ubase_t)cmd) { case FIONREAD: - *((int*)args) = rt_ringbuffer_data_len(pipe->fifo); - break; case FIONWRITE: - *((int*)args) = rt_ringbuffer_space_len(pipe->fifo); + { + int value = (cmd == FIONREAD) + ? (int)rt_ringbuffer_data_len(pipe->fifo) + : (int)rt_ringbuffer_space_len(pipe->fifo); +#ifdef RT_USING_LWP + if (!lwp_user_accessable(args, sizeof(value))) + { + return -EFAULT; + } + if (lwp_put_to_user(args, &value, sizeof(value)) != sizeof(value)) + { + return -EFAULT; + } +#else + *(int *)args = value; +#endif break; + } default: ret = -EINVAL; break;