From 004a16739d4c746b3b5e082d986a30bb21476f40 Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Wed, 24 May 2023 13:47:37 -0700 Subject: [PATCH] Check get_gwp_asan_callbacks before calling. When using the bootstrap linker, the get_gwp_asan_callbacks is not set. Therefore, check it is not nullptr before calling it during crash processing. Bug: 284098779 Test: Ran crasher64 using /system/bin/bootstrap/linker64 and verify Test: debuggerd code does not crash. Test: All unit tests pass. Change-Id: Ifc710fe4bef24661700444a1b69432bfc29d580f --- debuggerd/handler/debuggerd_handler.cpp | 32 ++++++++++++++----------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp index baa5bfb50..c6a535ad6 100644 --- a/debuggerd/handler/debuggerd_handler.cpp +++ b/debuggerd/handler/debuggerd_handler.cpp @@ -566,20 +566,23 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void* c process_info = g_callbacks.get_process_info(); } - // GWP-ASan catches use-after-free and heap-buffer-overflow by using PROT_NONE - // guard pages, which lead to SEGV. Normally, debuggerd prints a bug report - // and the process terminates, but in some cases, we actually want to print - // the bug report and let the signal handler return, and restart the process. - // In order to do that, we need to disable GWP-ASan's guard pages. The - // following callbacks handle this case. - gwp_asan_callbacks_t gwp_asan_callbacks = g_callbacks.get_gwp_asan_callbacks(); - if (signal_number == SIGSEGV && signal_has_si_addr(info) && - gwp_asan_callbacks.debuggerd_needs_gwp_asan_recovery && - gwp_asan_callbacks.debuggerd_gwp_asan_pre_crash_report && - gwp_asan_callbacks.debuggerd_gwp_asan_post_crash_report && - gwp_asan_callbacks.debuggerd_needs_gwp_asan_recovery(info->si_addr)) { - gwp_asan_callbacks.debuggerd_gwp_asan_pre_crash_report(info->si_addr); - process_info.recoverable_gwp_asan_crash = true; + gwp_asan_callbacks_t gwp_asan_callbacks = {}; + if (g_callbacks.get_gwp_asan_callbacks != nullptr) { + // GWP-ASan catches use-after-free and heap-buffer-overflow by using PROT_NONE + // guard pages, which lead to SEGV. Normally, debuggerd prints a bug report + // and the process terminates, but in some cases, we actually want to print + // the bug report and let the signal handler return, and restart the process. + // In order to do that, we need to disable GWP-ASan's guard pages. The + // following callbacks handle this case. + gwp_asan_callbacks = g_callbacks.get_gwp_asan_callbacks(); + if (signal_number == SIGSEGV && signal_has_si_addr(info) && + gwp_asan_callbacks.debuggerd_needs_gwp_asan_recovery && + gwp_asan_callbacks.debuggerd_gwp_asan_pre_crash_report && + gwp_asan_callbacks.debuggerd_gwp_asan_post_crash_report && + gwp_asan_callbacks.debuggerd_needs_gwp_asan_recovery(info->si_addr)) { + gwp_asan_callbacks.debuggerd_gwp_asan_pre_crash_report(info->si_addr); + process_info.recoverable_gwp_asan_crash = true; + } } // If sival_int is ~0, it means that the fallback handler has been called @@ -764,6 +767,7 @@ void debuggerd_init(debuggerd_callbacks_t* callbacks) { bool debuggerd_handle_signal(int signal_number, siginfo_t* info, void* context) { if (signal_number != SIGSEGV || !signal_has_si_addr(info)) return false; + if (g_callbacks.get_gwp_asan_callbacks == nullptr) return false; gwp_asan_callbacks_t gwp_asan_callbacks = g_callbacks.get_gwp_asan_callbacks(); if (gwp_asan_callbacks.debuggerd_needs_gwp_asan_recovery == nullptr || gwp_asan_callbacks.debuggerd_gwp_asan_pre_crash_report == nullptr ||