diff options
Diffstat (limited to 'libc/bionic/pthread_create.cpp')
-rw-r--r-- | libc/bionic/pthread_create.cpp | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp index d4a8bef26..121b26f82 100644 --- a/libc/bionic/pthread_create.cpp +++ b/libc/bionic/pthread_create.cpp @@ -30,6 +30,7 @@ #include <errno.h> #include <string.h> +#include <sys/auxv.h> #include <sys/mman.h> #include <sys/prctl.h> #include <sys/random.h> @@ -39,6 +40,7 @@ #include <async_safe/log.h> +#include "private/ScopedRWLock.h" #include "private/bionic_constants.h" #include "private/bionic_defs.h" #include "private/bionic_globals.h" @@ -329,6 +331,11 @@ void __set_stack_and_tls_vma_name(bool is_main_thread) { extern "C" int __rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t); __attribute__((no_sanitize("hwaddress"))) +#ifdef __aarch64__ +// This function doesn't return, but it does appear in stack traces. Avoid using return PAC in this +// function because we may end up resetting IA, which may confuse unwinders due to mismatching keys. +__attribute__((target("branch-protection=bti"))) +#endif static int __pthread_start(void* arg) { pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(arg); @@ -343,6 +350,16 @@ static int __pthread_start(void* arg) { __set_stack_and_tls_vma_name(false); __init_additional_stacks(thread); __rt_sigprocmask(SIG_SETMASK, &thread->start_mask, nullptr, sizeof(thread->start_mask)); +#ifdef __aarch64__ + // Chrome's sandbox prevents this prctl, so only reset IA if the target SDK level is high enough. + // Furthermore, processes loaded from vendor partitions may have their own sandboxes that would + // reject the prctl. Because no devices launched with PAC enabled before S, we can avoid issues on + // upgrading devices by checking for PAC support before issuing the prctl. + static const bool pac_supported = getauxval(AT_HWCAP) & HWCAP_PACA; + if (pac_supported && android_get_application_target_sdk_version() >= __ANDROID_API_S__) { + prctl(PR_PAC_RESET_KEYS, PR_PAC_APIAKEY, 0, 0, 0); + } +#endif void* result = thread->start_routine(thread->start_routine_arg); pthread_exit(result); @@ -350,13 +367,14 @@ static int __pthread_start(void* arg) { return 0; } -// A dummy start routine for pthread_create failures where we've created a thread but aren't +// A no-op start routine for pthread_create failures where we've created a thread but aren't // going to run user code on it. We swap out the user's start routine for this and take advantage // of the regular thread teardown to free up resources. static void* __do_nothing(void*) { return nullptr; } +pthread_rwlock_t g_thread_creation_lock = PTHREAD_RWLOCK_INITIALIZER; __BIONIC_WEAK_FOR_NATIVE_BRIDGE int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr, @@ -406,6 +424,8 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr, tls = &tls_descriptor; #endif + ScopedReadLock locker(&g_thread_creation_lock); + sigset64_t block_all_mask; sigfillset64(&block_all_mask); __rt_sigprocmask(SIG_SETMASK, &block_all_mask, &thread->start_mask, sizeof(thread->start_mask)); |