[hwasan] Tweak process and thread initialization.
Make sure that TLS_SLOT_TSAN is always available and correctly set up in
HWASan-instrumented functions by setting up the tls register and running hwasan
initialization (__hwasan_init in the main thread and __hwasan_thread_enter in
secondary) early enough.
This is needed to accomodate a change in HWASan: https://reviews.llvm.org/D52249
Bug: 112438058
Test: boot with SANITIZE_TARGET=hwaddress, run bionic-tests
Change-Id: Icd909a4ea0da6c6c1095522bcc28debef5f2c63d
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
index 8645df2..758b295 100644
--- a/libc/bionic/__libc_init_main_thread.cpp
+++ b/libc/bionic/__libc_init_main_thread.cpp
@@ -36,12 +36,18 @@
#include "private/bionic_ssp.h"
#include "pthread_internal.h"
-extern "C" int __set_tls(void* ptr);
extern "C" int __set_tid_address(int* tid_address);
// Declared in "private/bionic_ssp.h".
uintptr_t __stack_chk_guard = 0;
+static pthread_internal_t main_thread;
+
+__attribute__((no_sanitize("hwaddress")))
+pthread_internal_t* __get_main_thread() {
+ return &main_thread;
+}
+
// Setup for the main thread. For dynamic executables, this is called by the
// linker _before_ libc is mapped in memory. This means that all writes to
// globals from this function will apply to linker-private copies and will not
@@ -62,8 +68,6 @@
__libc_init_sysinfo(args);
#endif
- static pthread_internal_t main_thread;
-
// The -fstack-protector implementation uses TLS, so make sure that's
// set up before we call any function that might get a stack check inserted.
// TLS also needs to be set up before errno (and therefore syscalls) can be used.
diff --git a/libc/bionic/clone.cpp b/libc/bionic/clone.cpp
index b895305..2a6ab41 100644
--- a/libc/bionic/clone.cpp
+++ b/libc/bionic/clone.cpp
@@ -41,6 +41,7 @@
extern "C" __noreturn void __exit(int status);
// Called from the __bionic_clone assembler to call the thread function then exit.
+__attribute__((no_sanitize("hwaddress")))
extern "C" __LIBC_HIDDEN__ void __start_thread(int (*fn)(void*), void* arg) {
BIONIC_STOP_UNWIND;
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index 55506a3..38a04f8 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -127,20 +127,25 @@
exit(slingshot(args.argc, args.argv, args.envp));
}
-#if __has_feature(hwaddress_sanitizer)
+extern "C" void __hwasan_init();
+
__attribute__((no_sanitize("hwaddress")))
-#endif
__noreturn void __libc_init(void* raw_args,
void (*onexit)(void) __unused,
int (*slingshot)(int, char**, char**),
structors_array_t const * const structors) {
#if __has_feature(hwaddress_sanitizer)
- __hwasan_shadow_init();
+ // Install main thread TLS early. It will be initialized later in __libc_init_main_thread. For now
+ // all we need is access to TLS_SLOT_TSAN.
+ pthread_internal_t* main_thread = __get_main_thread();
+ __set_tls(main_thread->tls);
+ // Initialize HWASan. This sets up TLS_SLOT_TSAN, among other things.
+ __hwasan_init();
+ // We are ready to run HWASan-instrumented code, proceed with libc initialization...
#endif
__real_libc_init(raw_args, onexit, slingshot, structors);
}
-
static uint32_t g_target_sdk_version{__ANDROID_API__};
extern "C" uint32_t android_get_application_target_sdk_version() {
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 15366af..543fdc5 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -240,17 +240,18 @@
return 0;
}
+__attribute__((no_sanitize("hwaddress")))
static int __pthread_start(void* arg) {
pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(arg);
+ __hwasan_thread_enter();
+
// Wait for our creating thread to release us. This lets it have time to
// notify gdb about this thread before we start doing anything.
// This also provides the memory barrier needed to ensure that all memory
// accesses previously made by the creating thread are visible to us.
thread->startup_handshake_lock.lock();
- __hwasan_thread_enter();
-
__init_alternate_signal_stack(thread);
void* result = thread->start_routine(thread->start_routine_arg);
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 1ec201b..65ec5ff 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -151,6 +151,9 @@
return *__get_thread()->bionic_tls;
}
+extern __LIBC_HIDDEN__ pthread_internal_t* __get_main_thread();
+extern "C" __LIBC_HIDDEN__ int __set_tls(void* ptr);
+
__LIBC_HIDDEN__ void pthread_key_clean_all(void);
// Address space is precious on LP32, so use the minimum unit: one page.