Call the debuggerd first chance handler in sigchain for recoverable GWP-ASan am: d04ed70019 am: f9692238c5
Original change: https://android-review.googlesource.com/c/platform/art/+/2405485
Change-Id: I36b8038a42993c8945f19368717f77dcabe0d277
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc
index 668d75e..208f7ed 100644
--- a/sigchainlib/sigchain.cc
+++ b/sigchainlib/sigchain.cc
@@ -340,6 +340,12 @@
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 @@
}
}
+ // 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);