@samitouri / QOSamiQemu / commits / 7e966ef38f

bsd-user, linux-user: signal: recursive signal delivery fix

Synchronous signals must accommodate a synchronous signal being raised during delivery, as asynchronous ones do. For example badframe errors during delivery will cause SIGSEGV to be raised. Without this fix, cpu_loop() runs process_pending_signals() which delivers the first synchronous signal (e.g., SIGILL) which fails to set the handler and forces SIGSEGV, but that is not picked up. process_pending_signals() returns. Then cpu_loop() runs cpu_exec() again, which attempts to execute the same instruction, another SIGILL. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Reviewed-by: Warner Losh <imp@bsdimp.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20260321135624.581398-3-npiggin@gmail.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Nicholas Piggin committed Mar 21, 2026 at 23:56 UTC 7e966ef38f58f91e05a46fdfda4ba63a9a1567d6
2 files changed +12 -7
bsd-user/signal.c
+6 -4
@@ -998,7 +998,12 @@ void process_pending_signals(CPUArchState *env)
998 sigdelset(&ts->signal_mask, target_to_host_signal(sig));
999 sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
1000 }
1001 + /*
1002 + * Restart scan from the beginning, as handle_pending_signal
1003 + * might have resulted in a new synchronous signal (eg SIGSEGV).
1004 + */
1005 handle_pending_signal(env, sig, &ts->sync_signal);
1006 + goto restart_scan;
1007 }
1008
1009 k = ts->sigtab;
@@ -1008,10 +1013,7 @@ void process_pending_signals(CPUArchState *env)
1013 if (k->pending &&
1014 !sigismember(blocked_set, target_to_host_signal(sig))) {
1015 handle_pending_signal(env, sig, k);
1011 - /*
1012 - * Restart scan from the beginning, as handle_pending_signal
1013 - * might have resulted in a new synchronous signal (eg SIGSEGV).
1014 - */
1016 + /* Restart scan, explained above. */
1017 goto restart_scan;
1018 }
1019 }
linux-user/signal.c
+6 -3
@@ -1384,6 +1384,11 @@ void process_pending_signals(CPUArchState *cpu_env)
1384 }
1385
1386 handle_pending_signal(cpu_env, sig, &ts->sync_signal);
1387 + /*
1388 + * Restart scan from the beginning, as handle_pending_signal
1389 + * might have resulted in a new synchronous signal (eg SIGSEGV).
1390 + */
1391 + goto restart_scan;
1392 }
1393
1394 for (sig = 1; sig <= TARGET_NSIG; sig++) {
@@ -1394,9 +1399,7 @@ void process_pending_signals(CPUArchState *cpu_env)
1399 (!sigismember(blocked_set,
1400 target_to_host_signal_table[sig]))) {
1401 handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]);
1397 - /* Restart scan from the beginning, as handle_pending_signal
1398 - * might have resulted in a new synchronous signal (eg SIGSEGV).
1399 - */
1402 + /* Restart scan, explained above. */
1403 goto restart_scan;
1404 }
1405 }