arch/arm: redirect an M-profile thread to its signal action once

A signal action queued at syscall return pends PendSV for the running
thread, but the same SVC can switch to another thread first. PendSV then
saw that thread, the redirect was lost and the handler did not run until
a later PendSV landed on the target, which could happen while it was
already in arm_sigdeliver: the second redirect overwrote saved_regs, the
inner delivery cleared sigdeliver and the outer one branched to address
0. ostest sighand and signest hard faulted in a protected build.

The redirect is now checked against the thread being switched in, and a
thread already redirected is left alone until arm_sigdeliver restores
its context.

Signed-off-by: Royyan Zahir <royzah@gmail.com>
This commit is contained in:
Royyan Zahir 2026-10-08 19:41:36 +04:00 • committed by Alan C. Assis
parent 3e456050d3
commit 5f5991a0f2
9 changed files with 39 additions and 27 deletions

View file

@ -85,15 +85,6 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
/* Dispatch the PendSV interrupt */
irq_dispatch(irq, regs);
#endif
#ifdef CONFIG_ENABLE_ALL_SIGNALS
if (tcb->sigdeliver)
{
/* Pendsv able to access running tcb with no critical section */
up_schedule_sigaction(tcb);
}
#endif
up_irq_save();
}
@ -104,6 +95,13 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
tcb = this_task();
#ifdef CONFIG_ENABLE_ALL_SIGNALS
if (tcb->sigdeliver)
{
up_schedule_sigaction(tcb);
}
#endif
/* Update scheduler parameters.
* The arm-m architecture svc call will trigger an interrupt,
* and the actual context switch is executed after doirq is completed,

View file

@ -86,6 +86,11 @@ void up_schedule_sigaction(struct tcb_s *tcb)
struct tcb_s *rtcb = running_task();
uint32_t ipsr = getipsr();
if (tcb->xcp.saved_regs != NULL)
{
return;
}
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/

View file

@ -165,6 +165,7 @@ retry:
g_running_tasks[this_cpu()] = NULL;
rtcb->xcp.regs = rtcb->xcp.saved_regs;
rtcb->xcp.saved_regs = NULL;
arm_fullcontextrestore();
UNUSED(regs);
}

View file

@ -85,15 +85,6 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
/* Dispatch the PendSV interrupt */
irq_dispatch(irq, regs);
#endif
#ifdef CONFIG_ENABLE_ALL_SIGNALS
if (tcb->sigdeliver)
{
/* Pendsv able to access running tcb with no critical section */
up_schedule_sigaction(tcb);
}
#endif
up_irq_save();
@ -105,6 +96,13 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
tcb = this_task();
#ifdef CONFIG_ENABLE_ALL_SIGNALS
if (tcb->sigdeliver)
{
up_schedule_sigaction(tcb);
}
#endif
/* Update scheduler parameters.
* The arm-m architecture svc call will trigger an interrupt,
* and the actual context switch is executed after doirq is completed,

View file

@ -87,6 +87,11 @@ void up_schedule_sigaction(struct tcb_s *tcb)
struct tcb_s *rtcb = running_task();
uint32_t ipsr = getipsr();
if (tcb->xcp.saved_regs != NULL)
{
return;
}
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/

View file

@ -189,6 +189,7 @@ retry:
}
rtcb->xcp.regs = rtcb->xcp.saved_regs;
rtcb->xcp.saved_regs = NULL;
arm_fullcontextrestore();
UNUSED(regs);
}

View file

@ -97,15 +97,6 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
/* Dispatch the PendSV interrupt */
irq_dispatch(irq, regs);
#endif
#ifdef CONFIG_ENABLE_ALL_SIGNALS
if (tcb->sigdeliver)
{
/* Pendsv able to access running tcb with no critical section */
up_schedule_sigaction(tcb);
}
#endif
up_irq_save();
@ -117,6 +108,13 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
tcb = this_task();
#ifdef CONFIG_ENABLE_ALL_SIGNALS
if (tcb->sigdeliver)
{
up_schedule_sigaction(tcb);
}
#endif
/* Update scheduler parameters.
* The arm-m architecture svc call will trigger an interrupt,
* and the actual context switch is executed after doirq is completed,

View file

@ -87,6 +87,11 @@ void up_schedule_sigaction(struct tcb_s *tcb)
struct tcb_s *rtcb = running_task();
uint32_t ipsr = getipsr();
if (tcb->xcp.saved_regs != NULL)
{
return;
}
/* First, handle some special cases when the signal is
* being delivered to the currently executing task.
*/

View file

@ -189,6 +189,7 @@ retry:
}
rtcb->xcp.regs = rtcb->xcp.saved_regs;
rtcb->xcp.saved_regs = NULL;
arm_fullcontextrestore();
UNUSED(regs);
}