royzah opened a new pull request, #20539: URL: https://github.com/apache/nuttx/pull/20539
## Summary On ARMv6-M, ARMv7-M and ARMv8-M a signal action can be redirected twice, and the second redirect hard faults the thread. A signal that arrives while a thread is in a syscall is queued, and `SYS_syscall_return` dispatches it: `up_schedule_sigaction()` pends PendSV for the running thread. The same SVC can switch to another thread first (`sched_unlock()` in `nxsig_unmask_pendingsignal()`). PendSV then checks `sigdeliver` on the thread that is now running, not the target, so the redirect is lost, the target returns to user space without running its handler, and `sigdeliver` stays set. A later PendSV that lands on the target while it is already in `arm_sigdeliver()` redirects it again: `saved_regs` is overwritten, the inner delivery clears `sigdeliver`, and the outer one calls it as NULL and branches to address 0. This change: - checks `sigdeliver` in `arm_doirq()` on the thread being switched in, after the scheduler has picked it, instead of only on the thread PendSV interrupted - returns early from `up_schedule_sigaction()` while a redirect is active (`saved_regs != NULL`) - clears `saved_regs` in `arm_sigdeliver()` once the context is restored ## Impact Fixes a hard fault in signal delivery on ARMv6-M, ARMv7-M and ARMv8-M. Seen in a protected build under load; flat builds take the same `arm_doirq()` path. No API or configuration change. ## Testing Host: Ubuntu 24.04 x86_64, `ghcr.io/apache/nuttx/apache-nuttx-ci-linux`, `arm-none-eabi-gcc` 13.2.1, QEMU 6.2.0. Full logs: https://gist.github.com/royzah/2b82f04715cf2ce003a9bd64b71365ae **Hardware, Holybro Pixhawk 6X-RT (i.MX RT1176, ARMv7-M), protected build under load.** Downstream tree based on 12.11 carrying the same change. - before: in `sighand_test` the waiter's `sem_wait()` returns `EINTR` and it continues without running the handler, then the board hard faults with PC 0, LR in `arm_sigdeliver()` (`rt1176-before-*.log`) - after: full `ostest`, `Exiting with status 0` (`rt1176-after-ostest.log`) **QEMU** (does not reproduce the race: it needs a switch at syscall return under interrupt load, so these show no regression): | Config | master | this PR | | --- | --- | --- | | `mps2-an500:knsh` (ARMv7-M, protected) | `sighand`, `signest` (3720 signals) pass, `Exiting with status 0` | same | | `mps2-an500:nsh` (ARMv7-M, flat) | `sighand`, `signest` pass; `perf_gettime.c:132` asserts later | same | | `mps3-an547:knsh` (ARMv8-M, protected) | stops in `vfork_test`, before the signal tests | same | The `perf_gettime` assertion and the `vfork_test` stop are on master too. ARMv6-M: `nucleo-l073rz:nsh` builds; there is no protected QEMU target to run it on. `tools/checkpatch.sh -u -m -g` and codespell pass. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
