Skip to content

Commit

Permalink
linux-user: Remap guest SIGABRT
Browse files Browse the repository at this point in the history
Distinguish host SIGABRT from guest SIGABRT by mapping
the guest signal onto one of the host RT signals.

This prevents a cycle by which a host assertion failure
is caught and handled by host_signal_handler, queued for
the guest, and then we attempt to continue past the
host abort.  What happens next depends on the host libc,
but is neither good nor helpful.

Acked-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed Oct 18, 2023
1 parent 4a6ebc1 commit 38ee0a7
Showing 1 changed file with 35 additions and 7 deletions.
42 changes: 35 additions & 7 deletions linux-user/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -522,8 +522,21 @@ static void signal_table_init(void)
* multiplexed over a single host signal.
* Attempts for configure "missing" signals via sigaction will be
* silently ignored.
*
* Remap the target SIGABRT, so that we can distinguish host abort
* from guest abort. When the guest registers a signal handler or
* calls raise(SIGABRT), the host will raise SIG_RTn. If the guest
* arrives at dump_core_and_abort(), we will map back to host SIGABRT
* so that the parent (native or emulated) sees the correct signal.
* Finally, also map host to guest SIGABRT so that the emulated
* parent sees the correct mapping from wait status.
*/
for (hsig = SIGRTMIN; hsig <= SIGRTMAX; hsig++) {

hsig = SIGRTMIN;
host_to_target_signal_table[SIGABRT] = 0;
host_to_target_signal_table[hsig++] = TARGET_SIGABRT;

for (; hsig <= SIGRTMAX; hsig++) {
tsig = hsig - SIGRTMIN + TARGET_SIGRTMIN;
if (tsig <= TARGET_NSIG) {
host_to_target_signal_table[hsig] = tsig;
Expand All @@ -539,6 +552,8 @@ static void signal_table_init(void)
}
}

host_to_target_signal_table[SIGABRT] = TARGET_SIGABRT;

/* Map everything else out-of-bounds. */
for (hsig = 1; hsig < _NSIG; hsig++) {
if (host_to_target_signal_table[hsig] == 0) {
Expand Down Expand Up @@ -582,13 +597,21 @@ void signal_init(void)
int hsig = target_to_host_signal(tsig);
abi_ptr thand = TARGET_SIG_IGN;

if (hsig < _NSIG) {
struct sigaction *iact = core_dump_signal(tsig) ? &act : NULL;
if (hsig >= _NSIG) {
continue;
}

/* As we force remap SIGABRT, cannot probe and install in one step. */
if (tsig == TARGET_SIGABRT) {
sigaction(SIGABRT, NULL, &oact);
sigaction(hsig, &act, NULL);
} else {
struct sigaction *iact = core_dump_signal(tsig) ? &act : NULL;
sigaction(hsig, iact, &oact);
if (oact.sa_sigaction != (void *)SIG_IGN) {
thand = TARGET_SIG_DFL;
}
}

if (oact.sa_sigaction != (void *)SIG_IGN) {
thand = TARGET_SIG_DFL;
}
sigact_table[tsig - 1]._sa_handler = thand;
}
Expand Down Expand Up @@ -711,7 +734,12 @@ void dump_core_and_abort(CPUArchState *env, int target_sig)
TaskState *ts = (TaskState *)cpu->opaque;
int host_sig, core_dumped = 0;

host_sig = target_to_host_signal(target_sig);
/* On exit, undo the remapping of SIGABRT. */
if (target_sig == TARGET_SIGABRT) {
host_sig = SIGABRT;
} else {
host_sig = target_to_host_signal(target_sig);
}
trace_user_dump_core_and_abort(env, target_sig, host_sig);
gdb_signalled(env, target_sig);

Expand Down

0 comments on commit 38ee0a7

Please sign in to comment.