diff options
author | Rich Felker <dalias@aerifal.cx> | 2018-09-01 01:54:44 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2018-09-01 02:06:10 -0400 |
commit | 9b14ad541068d4f7d0be9bcd1ff4c70090d868d3 (patch) | |
tree | ee80fd4be7d6d4a96858e02d76e4b53f038bf35d /src/exit | |
parent | 0b4c92b7acf63529858e7f8a3bb6505cd2b6e962 (diff) | |
download | musl-9b14ad541068d4f7d0be9bcd1ff4c70090d868d3.tar.gz musl-9b14ad541068d4f7d0be9bcd1ff4c70090d868d3.tar.bz2 musl-9b14ad541068d4f7d0be9bcd1ff4c70090d868d3.tar.xz musl-9b14ad541068d4f7d0be9bcd1ff4c70090d868d3.zip |
always terminate by SIGABRT when abort is called
Linux makes this surprisingly difficult, but it can be done. the trick
here is using the fact that we control the implementation of sigaction
to prevent changing the disposition of SIGABRT to anything but SIG_DFL
after abort has tried and failed to terminate the process simply by
calling raise(SIGABRT).
Diffstat (limited to 'src/exit')
-rw-r--r-- | src/exit/abort.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/src/exit/abort.c b/src/exit/abort.c index ecc0f735..d6bd546b 100644 --- a/src/exit/abort.c +++ b/src/exit/abort.c @@ -3,11 +3,30 @@ #include "syscall.h" #include "pthread_impl.h" #include "atomic.h" +#include "libc.h" +#include "ksigaction.h" + +__attribute__((__visibility__("hidden"))) +volatile int __abort_lock[1]; _Noreturn void abort(void) { raise(SIGABRT); + + /* If there was a SIGABRT handler installed and it returned, or if + * SIGABRT was blocked or ignored, take an AS-safe lock to prevent + * sigaction from installing a new SIGABRT handler, uninstall any + * handler that may be present, and re-raise the signal to generate + * the default action of abnormal termination. */ __block_all_sigs(0); + LOCK(__abort_lock); + __syscall(SYS_rt_sigaction, SIGABRT, + &(struct k_sigaction){.handler = SIG_DFL}, 0, _NSIG/8); + __syscall(SYS_tkill, __pthread_self()->tid, SIGABRT); + __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, + &(long[_NSIG/(8*sizeof(long))]){1UL<<(SIGABRT-1)}, 0, _NSIG/8); + + /* Beyond this point should be unreachable. */ a_crash(); raise(SIGKILL); _Exit(127); |