[GWP-ASan] Fix non-reentrant libc_globals init behaviour.
The WriteProtected mutator for __libc_globals isn't reentrant.
Previously we were calling __libc_globals.mutate() inside of GWP-ASan's
libc initialisation, which is called inside the __libc_globals.mutate().
This causes problems with malloc_debug and other malloc shims, as they
fail to install when GWP-ASan is sampling their processes.
Bug: 135634846
Test: atest bionic
Change-Id: Iae51faa8d78677eeab6204b6ab4f3ae1b7517ba5
diff --git a/libc/bionic/gwp_asan_wrappers.cpp b/libc/bionic/gwp_asan_wrappers.cpp
index 680c5e7..1feb871 100644
--- a/libc/bionic/gwp_asan_wrappers.cpp
+++ b/libc/bionic/gwp_asan_wrappers.cpp
@@ -195,7 +195,7 @@
return false;
}
-bool MaybeInitGwpAsanFromLibc() {
+bool MaybeInitGwpAsanFromLibc(libc_globals* globals) {
// Never initialize the Zygote here. A Zygote chosen for sampling would also
// have all of its children sampled. Instead, the Zygote child will choose
// whether it samples or not just after the Zygote forks. For
@@ -205,14 +205,14 @@
if (progname && strncmp(progname, "app_process", 11) == 0) {
return false;
}
- return MaybeInitGwpAsan(false);
+ return MaybeInitGwpAsan(globals);
}
static bool GwpAsanInitialized = false;
// Maybe initializes GWP-ASan. Called by android_mallopt() and libc's
// initialisation. This should always be called in a single-threaded context.
-bool MaybeInitGwpAsan(bool force_init) {
+bool MaybeInitGwpAsan(libc_globals* globals, bool force_init) {
if (GwpAsanInitialized) {
error_log("GWP-ASan was already initialized for this process.");
return false;
@@ -239,17 +239,15 @@
// GWP-ASan's initialization is always called in a single-threaded context, so
// we can initialize lock-free.
- __libc_globals.mutate([](libc_globals* globals) {
- // Set GWP-ASan as the malloc dispatch table.
- globals->malloc_dispatch_table = gwp_asan_dispatch;
- atomic_store(&globals->default_dispatch_table, &gwp_asan_dispatch);
+ // Set GWP-ASan as the malloc dispatch table.
+ globals->malloc_dispatch_table = gwp_asan_dispatch;
+ atomic_store(&globals->default_dispatch_table, &gwp_asan_dispatch);
- // If malloc_limit isn't installed, we can skip the default_dispatch_table
- // lookup.
- if (GetDispatchTable() == nullptr) {
- atomic_store(&globals->current_dispatch_table, &gwp_asan_dispatch);
- }
- });
+ // If malloc_limit isn't installed, we can skip the default_dispatch_table
+ // lookup.
+ if (GetDispatchTable() == nullptr) {
+ atomic_store(&globals->current_dispatch_table, &gwp_asan_dispatch);
+ }
#ifndef LIBC_STATIC
SetGlobalFunctions(gwp_asan_gfunctions);