From 311069da9c36dbca29b53740b3bba1d05f35b6da Mon Sep 17 00:00:00 2001 From: Junbo Zheng Date: Mon, 20 Jul 2026 16:52:46 +0800 Subject: [PATCH] arch/arm: set PSPLIM to top of TLS region to protect it from overflow A crash was observed when running ps: a BusFault in nxtask_argvstr dereferencing tl_argv, because a thread's stack overflow had silently corrupted the TLS region where tl_argv resides. On ARMv8-M with CONFIG_ARMV8M_STACKCHECK_HARDWARE, PSPLIM was set to stack_alloc_ptr -- the bottom of the allocation where TLS begins. The stack grows downward and TLS occupies [stack_alloc_ptr, stack_alloc_ptr + tls_info_size()), so an overflow crossed into TLS and clobbered tl_argv before SP reached the limit, going undetected until code that read the corrupted TLS data (such as ps) hit the bad pointer. Set the limit to stack_alloc_ptr + tls_info_size() -- the top of the TLS region and the usable stack base -- so an overflow faults at the TLS boundary, before any TLS byte is touched. Include for the tls_info_size() macro, which is the value sched reserves for the TLS region via up_stack_frame(). Signed-off-by: Junbo Zheng --- arch/arm/src/armv8-m/arm_initialstate.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/src/armv8-m/arm_initialstate.c b/arch/arm/src/armv8-m/arm_initialstate.c index 162335b9d66..962050fa2c0 100644 --- a/arch/arm/src/armv8-m/arm_initialstate.c +++ b/arch/arm/src/armv8-m/arm_initialstate.c @@ -31,6 +31,7 @@ #include #include +#include #include #include "arm_internal.h" @@ -106,9 +107,13 @@ void up_initial_state(struct tcb_s *tcb) #endif #ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE - /* Save the stack limit value, will be used in context switch. */ + /* Save the stack limit (restored on context switch) at the top of the + * TLS region. The stack grows downward and TLS occupies the bottom of + * the allocation, so an overflow faults here before it clobbers TLS + * data instead of silently corrupting it first. + */ - xcp->regs[REG_SPLIM] = (uint32_t)tcb->stack_alloc_ptr; + xcp->regs[REG_SPLIM] = (uint32_t)tcb->stack_alloc_ptr + tls_info_size(); #endif /* Save the task entry point (stripping off the thumb bit) */