Hold the loader mutex in linker_main once constructors are running
A constructor could spawn a thread, which could call into the loader,
so the global loader mutex must be held.
Bug: http://b/290318196
Test: treehugger
Change-Id: I7a5249898a11fbc62d1ecdb85b24017a42a4b179
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index a3f5246..fee19f4 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -97,7 +97,7 @@
void* context) __LINKER_PUBLIC__;
}
-static pthread_mutex_t g_dl_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+pthread_mutex_t g_dl_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
static char* __bionic_set_dlerror(char* new_value) {
char* old_value = __get_thread()->current_dlerror;
diff --git a/linker/linker_globals.h b/linker/linker_globals.h
index 0998629..0cb7ca9 100644
--- a/linker/linker_globals.h
+++ b/linker/linker_globals.h
@@ -104,3 +104,4 @@
};
__LIBC_HIDDEN__ extern bool g_is_ldd;
+__LIBC_HIDDEN__ extern pthread_mutex_t g_dl_mutex;
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index f7c8ea9..e92aada 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -43,10 +43,11 @@
#include "linker_tls.h"
#include "linker_utils.h"
+#include "private/KernelArgumentBlock.h"
+#include "private/ScopedPthreadMutexLocker.h"
#include "private/bionic_call_ifunc_resolver.h"
#include "private/bionic_globals.h"
#include "private/bionic_tls.h"
-#include "private/KernelArgumentBlock.h"
#include "android-base/unique_fd.h"
#include "android-base/strings.h"
@@ -498,6 +499,11 @@
if (!get_cfi_shadow()->InitialLinkDone(solist)) __linker_cannot_link(g_argv[0]);
+ // A constructor could spawn a thread that calls into the loader, so as soon
+ // as we've called a constructor, we need to hold the lock while accessing
+ // global loader state.
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+
si->call_pre_init_constructors();
si->call_constructors();