aboutsummaryrefslogtreecommitdiff
path: root/libc/bionic/pthread_create.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libc/bionic/pthread_create.cpp')
-rw-r--r--libc/bionic/pthread_create.cpp22
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));