From aecdabb625841052a68fd3b5510c56b138693c9a Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sat, 23 Nov 2024 15:39:03 -0500 Subject: sighook: Return instead of re-raising for faults This makes the death look exactly like it would if we didn't handle the signal at all. Coredumps will point at the right instruction, segfaults will get logged in dmesg again, etc. Technically POSIX says this is undefined, but if we get a fault, we've already done something undefined anyway ;) Link: https://github.com/rust-lang/rust/issues/26458 --- src/sighook.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/sighook.c b/src/sighook.c index cd17e42..a294206 100644 --- a/src/sighook.c +++ b/src/sighook.c @@ -425,13 +425,19 @@ static enum sigflags run_hooks(struct siglist *list, int sig, siginfo_t *info) { /** Dispatches a signal to the registered handlers. */ static void sigdispatch(int sig, siginfo_t *info, void *context) { - // https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_04_03_03 + // If we get a fault (e.g. a "real" SIGSEGV, not something like + // kill(..., SIGSEGV)), don't try to run signal hooks, since we could be + // in an arbitrarily corrupted state. // - // The behavior of a process is undefined after it returns normally - // from a signal-catching function for a SIGBUS, SIGFPE, SIGILL, or - // SIGSEGV signal that was not generated by kill(), sigqueue(), or - // raise(). + // POSIX says that returning normally from a signal handler for a fault + // is undefined. But in practice, it's better to uninstall the handler + // and return, which will re-run the faulting instruction and cause us + // to die "correctly" (e.g. with a core dump pointing at the faulting + // instruction, not reraise()). if (is_fault(info)) { + if (signal(sig, SIG_DFL) != SIG_ERR) { + return; + } reraise(sig); } -- cgit v1.2.3