From 839ae82d66a60926c616b023aba4080f999931f9 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Tue, 26 May 2020 13:15:59 +0300 Subject: [PATCH] LibC: Ensure abort() doesn't return It's not enough to send ourselves a SIGABRT, as it may be ignored or handled differently. We really, really want abort() to never return, as that will mess up the assumptions of the calling code big time. So, if raise(SIGABRT) returns, kill ourselves with SIGKILL, and if that somehow returns too, call _exit(). An alternative approach, which glibc apparently follows, is to reset SIGABRT disposition to its default value and then send SIGABRT to yourself a second time. That would also work, but I believe SIGKILL + _exit() to be a simpler approach that is less likely to break in extremely weird situations. Note that this only guarantees that abort() never returns, not that the process actually gets killed. It's still possible to install a SIGABRT handler that simply never returns (such as by longjmp'ing out, endlessly looping, or exec'ing another image). That is a legitimate use case we want to support; at the same time most software doesn't use that functionality and would benefit from hard guarantees that abort() terminates the program. The following commit is going to introduce means for ensuring SIGABRT handler is never reset to something unexpected. --- Libraries/LibC/stdlib.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Libraries/LibC/stdlib.cpp b/Libraries/LibC/stdlib.cpp index 2a97e507da..cc2d82da36 100644 --- a/Libraries/LibC/stdlib.cpp +++ b/Libraries/LibC/stdlib.cpp @@ -222,8 +222,11 @@ int atexit(void (*handler)()) void abort() { + // For starters, send ourselves a SIGABRT. raise(SIGABRT); - ASSERT_NOT_REACHED(); + // If that didn't kill us, try harder. + raise(SIGKILL); + _exit(127); } static HashTable s_malloced_environment_variables;