diff options
Diffstat (limited to 'libc/bionic/pthread_create.cpp')
-rw-r--r-- | libc/bionic/pthread_create.cpp | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp index ff972c3ec..7a266501d 100644 --- a/libc/bionic/pthread_create.cpp +++ b/libc/bionic/pthread_create.cpp @@ -50,7 +50,7 @@ void __init_user_desc(struct user_desc*, bool, void*); #endif // This code is used both by each new pthread and the code that initializes the main thread. -void __init_tls(pthread_internal_t* thread) { +bool __init_tls(pthread_internal_t* thread) { // Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0. thread->tls[TLS_SLOT_SELF] = thread->tls; thread->tls[TLS_SLOT_THREAD_ID] = thread; @@ -59,15 +59,24 @@ void __init_tls(pthread_internal_t* thread) { size_t allocation_size = BIONIC_TLS_SIZE + 2 * PAGE_SIZE; void* allocation = mmap(nullptr, allocation_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (allocation == MAP_FAILED) { - async_safe_fatal("failed to allocate TLS: %s", strerror(errno)); + async_safe_format_log(ANDROID_LOG_WARN, "libc", + "pthread_create failed: couldn't allocate TLS: %s", strerror(errno)); + return false; } - prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, allocation, allocation_size, "bionic TLS guard page"); + prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, allocation, allocation_size, "bionic TLS guard"); + + // Carve out the writable TLS section. thread->bionic_tls = reinterpret_cast<bionic_tls*>(static_cast<char*>(allocation) + PAGE_SIZE); if (mprotect(thread->bionic_tls, BIONIC_TLS_SIZE, PROT_READ | PROT_WRITE) != 0) { - async_safe_fatal("failed to mprotect TLS: %s", strerror(errno)); + async_safe_format_log(ANDROID_LOG_WARN, "libc", + "pthread_create failed: couldn't mprotect TLS: %s", strerror(errno)); + munmap(allocation, allocation_size); + return false; } + prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, thread->bionic_tls, BIONIC_TLS_SIZE, "bionic TLS"); + return true; } void __init_thread_stack_guard(pthread_internal_t* thread) { @@ -192,7 +201,10 @@ static int __allocate_thread(pthread_attr_t* attr, pthread_internal_t** threadp, thread->mmap_size = mmap_size; thread->attr = *attr; - __init_tls(thread); + if (!__init_tls(thread)) { + if (thread->mmap_size != 0) munmap(thread->attr.stack_base, thread->mmap_size); + return EAGAIN; + } __init_thread_stack_guard(thread); *threadp = thread; |