mirror of
https://github.com/qemu/qemu.git
synced 2026-04-05 21:46:25 +00:00
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>
This commit is contained in:
committed by
Peter Maydell
parent
fa6dfcc373
commit
7e966ef38f
@@ -998,7 +998,12 @@ void process_pending_signals(CPUArchState *env)
|
|||||||
sigdelset(&ts->signal_mask, target_to_host_signal(sig));
|
sigdelset(&ts->signal_mask, target_to_host_signal(sig));
|
||||||
sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
|
sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Restart scan from the beginning, as handle_pending_signal
|
||||||
|
* might have resulted in a new synchronous signal (eg SIGSEGV).
|
||||||
|
*/
|
||||||
handle_pending_signal(env, sig, &ts->sync_signal);
|
handle_pending_signal(env, sig, &ts->sync_signal);
|
||||||
|
goto restart_scan;
|
||||||
}
|
}
|
||||||
|
|
||||||
k = ts->sigtab;
|
k = ts->sigtab;
|
||||||
@@ -1008,10 +1013,7 @@ void process_pending_signals(CPUArchState *env)
|
|||||||
if (k->pending &&
|
if (k->pending &&
|
||||||
!sigismember(blocked_set, target_to_host_signal(sig))) {
|
!sigismember(blocked_set, target_to_host_signal(sig))) {
|
||||||
handle_pending_signal(env, sig, k);
|
handle_pending_signal(env, sig, k);
|
||||||
/*
|
/* Restart scan, explained above. */
|
||||||
* Restart scan from the beginning, as handle_pending_signal
|
|
||||||
* might have resulted in a new synchronous signal (eg SIGSEGV).
|
|
||||||
*/
|
|
||||||
goto restart_scan;
|
goto restart_scan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1384,6 +1384,11 @@ void process_pending_signals(CPUArchState *cpu_env)
|
|||||||
}
|
}
|
||||||
|
|
||||||
handle_pending_signal(cpu_env, sig, &ts->sync_signal);
|
handle_pending_signal(cpu_env, sig, &ts->sync_signal);
|
||||||
|
/*
|
||||||
|
* Restart scan from the beginning, as handle_pending_signal
|
||||||
|
* might have resulted in a new synchronous signal (eg SIGSEGV).
|
||||||
|
*/
|
||||||
|
goto restart_scan;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (sig = 1; sig <= TARGET_NSIG; sig++) {
|
for (sig = 1; sig <= TARGET_NSIG; sig++) {
|
||||||
@@ -1394,9 +1399,7 @@ void process_pending_signals(CPUArchState *cpu_env)
|
|||||||
(!sigismember(blocked_set,
|
(!sigismember(blocked_set,
|
||||||
target_to_host_signal_table[sig]))) {
|
target_to_host_signal_table[sig]))) {
|
||||||
handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]);
|
handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]);
|
||||||
/* Restart scan from the beginning, as handle_pending_signal
|
/* Restart scan, explained above. */
|
||||||
* might have resulted in a new synchronous signal (eg SIGSEGV).
|
|
||||||
*/
|
|
||||||
goto restart_scan;
|
goto restart_scan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user