arch/x86_64: run the signal trampoline on the thread kernel stack

For a thread interrupted in user mode the trampoline ran on the user
stack, where the signal handler then grows over its frame. Run it on
the thread kernel stack, unused while the thread is in user mode. The
stack cannot be selected from the saved CS: up_initial_state() records
the caller CS, a kernel selector even for user threads.

Signed-off-by: raiden00pl <raiden00@railab.me>
Assisted-by: Claude Code
This commit is contained in:
raiden00pl 2026-08-10 12:35:23 +02:00 committed by Xiang Xiao
parent 4405b12155
commit 2c79c9951b

View file

@ -74,6 +74,8 @@
void up_schedule_sigaction(struct tcb_s *tcb)
{
uint64_t sp = tcb->xcp.regs[REG_RSP];
sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
this_task(), this_task()->xcp.regs);
@ -83,7 +85,7 @@ void up_schedule_sigaction(struct tcb_s *tcb)
*/
tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP];
tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP];
tcb->xcp.saved_rsp = sp;
tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS];
/* Then set up to vector to the trampoline with interrupts
@ -91,6 +93,21 @@ void up_schedule_sigaction(struct tcb_s *tcb)
*/
tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver;
tcb->xcp.regs[REG_RSP] = tcb->xcp.regs[REG_RSP] - 8;
tcb->xcp.regs[REG_RFLAGS] = 0;
#ifdef CONFIG_ARCH_KERNEL_STACK
/* Run the trampoline on the thread kernel stack when the thread was
* interrupted in user mode: the signal handler runs on the user
* stack and would overwrite the trampoline frame there.
*/
if (tcb->xcp.kstack != NULL &&
(sp < (uint64_t)tcb->xcp.kstack || sp > (uint64_t)tcb->xcp.ktopstk))
{
tcb->xcp.saved_ursp = sp;
sp = (uint64_t)tcb->xcp.ktopstk;
}
#endif
tcb->xcp.regs[REG_RSP] = sp - 8;
}