From 02f4be4b5973e0621b1302fda58ee01e57e40db5 Mon Sep 17 00:00:00 2001 From: seteiro Date: Mon, 2 Nov 2026 15:23:08 +0800 Subject: [PATCH 1/2] 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; From f721512ba54322a26282a007975b23d99a38c5c6 Mon Sep 17 00:00:00 2001 From: seteiro Date: Wed, 4 Nov 2026 14:56:50 +0800 Subject: [PATCH 2/2] drivers/ipc: skip LWP copyout for kernel pipe ioctl Only use lwp_user_accessable/lwp_put_to_user when lwp_self()!=NULL; kernel callers keep direct *(int*)args write, matching serial. --- components/drivers/ipc/pipe.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/components/drivers/ipc/pipe.c b/components/drivers/ipc/pipe.c index e1e32af9797c..2aa544ed6d5b 100644 --- a/components/drivers/ipc/pipe.c +++ b/components/drivers/ipc/pipe.c @@ -11,6 +11,7 @@ * 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 + * 2026-11-04 seteiro pipe ioctl: skip LWP copyout for kernel callers (lwp_self()==NULL) */ #include #include @@ -208,17 +209,20 @@ static int pipe_fops_ioctl(struct dfs_file *fd, int cmd, void *args) ? (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))) + if (lwp_self() != RT_NULL) { - return -EFAULT; - } - if (lwp_put_to_user(args, &value, sizeof(value)) != sizeof(value)) - { - return -EFAULT; + if (!lwp_user_accessable(args, sizeof(value))) + { + return -EFAULT; + } + if (lwp_put_to_user(args, &value, sizeof(value)) != sizeof(value)) + { + return -EFAULT; + } + break; } -#else - *(int *)args = value; #endif + *(int *)args = value; break; } default: