From e782227b6cab5888ad0618235f8274e0ad010977 Mon Sep 17 00:00:00 2001 From: bernard Date: Mon, 19 Oct 2026 08:49:14 +0800 Subject: [PATCH] [components][lwp] Validate signal number in sys_sigaction sys_sigaction() forwarded the user-supplied signal number to lwp_signal_action() without any range check. lwp_signal_action() indexes the fixed-size sig_action[] and sig_action_mask[] arrays (_LWP_NSIG = 64) with signo - 1, so an out-of-range or negative signal caused out-of-bounds accesses in the kernel heap: - arbitrary-offset 8-byte write with a user-controlled handler value - kernel heap disclosure through the oact copy-out path - kernel crash when a far offset hits an unmapped address Reject signals outside [1, _LWP_NSIG] with EINVAL at the syscall entry, and add the same guard to lwp_signal_action() so future callers cannot reach the indexing code with an invalid signal. Verified on qemu-virt64-aarch64 and qemu-virt64-riscv (RT-Smart) with a user-space PoC: in-range signals still succeed, while 0, -1, 65, 200 and 0x1000000 now return -EINVAL without touching the arrays. Co-authored-by: DeepSeek 4.1 Flash --- components/lwp/lwp_signal.c | 6 ++++++ components/lwp/lwp_syscall.c | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/components/lwp/lwp_signal.c b/components/lwp/lwp_signal.c index 8c88e68151ee..7c8b746bbd9c 100644 --- a/components/lwp/lwp_signal.c +++ b/components/lwp/lwp_signal.c @@ -1114,6 +1114,12 @@ rt_err_t lwp_signal_action(struct rt_lwp *lwp, int signo, rt_list_t *thread_list; rt_err_t ret = RT_EOK; + /* Signal numbers are 1-based, reject out-of-range values before indexing */ + if (signo <= 0 || valid_signo_check(signo)) + { + return -RT_EINVAL; + } + if (lwp) { /** acquire READ access to lwp */ diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index a871f71b513e..c36464cd95c3 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -6752,6 +6752,11 @@ sysret_t sys_sigaction(int sig, const struct k_sigaction *act, struct lwp_sigaction kact, *pkact = RT_NULL; struct lwp_sigaction koact, *pkoact = RT_NULL; + if (sig <= 0 || (unsigned long)sig > _LWP_NSIG) + { + SET_ERRNO(EINVAL); + goto out; + } if (!sigsetsize) { SET_ERRNO(EINVAL);