diff options
| -rw-r--r-- | sigchainlib/sigchain.cc | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc index 668d75e63c..208f7ed1f2 100644 --- a/sigchainlib/sigchain.cc +++ b/sigchainlib/sigchain.cc @@ -340,6 +340,12 @@ static SignalChain chains[_NSIG + 1]; static bool is_signal_hook_debuggable = false; +// Weak linkage, as the ART APEX might be deployed on devices where this symbol doesn't exist (i.e. +// all OS's before Android U). This symbol comes from libdl. +__attribute__((weak)) extern "C" bool android_handle_signal(int signal_number, + siginfo_t* info, + void* context); + void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) { // Try the special handlers first. // If one of them crashes, we'll reenter this handler and pass that crash onto the user handler. @@ -369,6 +375,25 @@ void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) { } } + // In Android 14, there's a special feature called "recoverable" GWP-ASan. GWP-ASan is a tool that + // finds heap-buffer-overflow and heap-use-after-free on native heap allocations (e.g. malloc() + // inside of JNI, not the ART heap). The way it catches buffer overflow (roughly) is by rounding + // up the malloc() so that it's page-sized, and mapping an inaccessible page on the left- and + // right-hand side. It catches use-after-free by mprotecting the allocation page to be PROT_NONE + // on free(). The new "recoverable" mode is designed to allow debuggerd to print a crash report, + // but for the app or process in question to not crash (i.e. recover) and continue even after the + // bug is detected. Sigchain thus must allow debuggerd to handle the signal first, and if + // debuggerd has promised that it can recover, and it's done the steps to allow recovery (as + // identified by android_handle_signal returning true), then we should return from this handler + // and let the app continue. + // + // For all non-GWP-ASan-recoverable crashes, or crashes where recovery is not possible, + // android_handle_signal returns false, and we will continue to the rest of the sigchain handler + // logic. + if (android_handle_signal != nullptr && android_handle_signal(signo, siginfo, ucontext_raw)) { + return; + } + // Forward to the user's signal handler. int handler_flags = chains[signo].action_.sa_flags; ucontext_t* ucontext = static_cast<ucontext_t*>(ucontext_raw); |