diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2017-10-03 07:29:46 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2017-10-03 07:29:46 +0000 |
commit | fcabaf45b7a17a2b67b3a7cc019da4b396966bce (patch) | |
tree | d9e4a3e7a14293d7397d1f5d9690703d55f195f4 | |
parent | 1ec3ea35f4bda556f8a2201ce4573a859271769a (diff) | |
parent | 854556c41e20c37b210498b0374415b640104785 (diff) | |
download | bionic-oreo-mr1-wear-release.tar.gz |
Snap for 4373604 from 854556c41e20c37b210498b0374415b640104785 to oc-mr1-releaseandroid-wear-8.1.0_r1android-security-8.1.0_r93android-security-8.1.0_r92android-security-8.1.0_r91android-security-8.1.0_r90android-security-8.1.0_r89android-security-8.1.0_r88android-security-8.1.0_r87android-security-8.1.0_r86android-security-8.1.0_r85android-security-8.1.0_r84android-security-8.1.0_r83android-security-8.1.0_r82android-cts-8.1_r8android-cts-8.1_r7android-cts-8.1_r6android-cts-8.1_r5android-cts-8.1_r4android-cts-8.1_r3android-cts-8.1_r2android-cts-8.1_r1android-8.1.0_r81android-8.1.0_r80android-8.1.0_r79android-8.1.0_r78android-8.1.0_r77android-8.1.0_r76android-8.1.0_r75android-8.1.0_r74android-8.1.0_r73android-8.1.0_r72android-8.1.0_r71android-8.1.0_r70android-8.1.0_r69android-8.1.0_r68android-8.1.0_r66android-8.1.0_r6android-8.1.0_r5android-8.1.0_r4android-8.1.0_r3android-8.1.0_r23android-8.1.0_r19android-8.1.0_r16android-8.1.0_r15android-8.1.0_r12android-8.1.0_r11android-8.1.0_r10android-8.1.0_r1security-oc-mr1-releaseoreo-mr1-wear-releaseoreo-mr1-security-releaseoreo-mr1-s1-releaseoreo-mr1-releaseoreo-mr1-cuttlefish-testingoreo-m4-s1-release
Change-Id: Ic1e94cd5376d06b8cf7b4c26d3f1aec31311159d
-rw-r--r-- | libc/async_safe/async_safe_log.cpp | 15 | ||||
-rw-r--r-- | libc/bionic/__libc_init_main_thread.cpp | 2 | ||||
-rw-r--r-- | libc/bionic/pthread_create.cpp | 22 | ||||
-rw-r--r-- | libc/bionic/pthread_internal.h | 2 | ||||
-rwxr-xr-x | tests/pthread_test.cpp | 46 |
5 files changed, 66 insertions, 21 deletions
diff --git a/libc/async_safe/async_safe_log.cpp b/libc/async_safe/async_safe_log.cpp index 99ff0c7f9..bc2a7999a 100644 --- a/libc/async_safe/async_safe_log.cpp +++ b/libc/async_safe/async_safe_log.cpp @@ -477,19 +477,6 @@ static int open_log_socket() { return log_fd; } -static clockid_t log_clockid() { - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - ScopedPthreadMutexLocker locker(&mutex); - - static CachedProperty ro_logd_timestamp("ro.logd.timestamp"); - static CachedProperty persist_logd_timestamp("persist.logd.timestamp"); - - char ch = persist_logd_timestamp.Get()[0]; - if (ch == '\0') ch = ro_logd_timestamp.Get()[0]; - - return (tolower(ch) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME; -} - struct log_time { // Wire format uint32_t tv_sec; uint32_t tv_nsec; @@ -510,7 +497,7 @@ int async_safe_write_log(int priority, const char* tag, const char* msg) { vec[1].iov_base = &tid; vec[1].iov_len = sizeof(tid); timespec ts; - clock_gettime(log_clockid(), &ts); + clock_gettime(CLOCK_REALTIME, &ts); log_time realtime_ts; realtime_ts.tv_sec = ts.tv_sec; realtime_ts.tv_nsec = ts.tv_nsec; diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp index f3dbfa537..9cbff11af 100644 --- a/libc/bionic/__libc_init_main_thread.cpp +++ b/libc/bionic/__libc_init_main_thread.cpp @@ -70,7 +70,7 @@ void __libc_init_main_thread(KernelArgumentBlock& args) { // 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. __set_tls(main_thread.tls); - __init_tls(&main_thread); + if (!__init_tls(&main_thread)) async_safe_fatal("failed to initialize TLS: %s", strerror(errno)); // Tell the kernel to clear our tid field when we exit, so we're like any other pthread. // As a side-effect, this tells us our pid (which is the same as the main thread's tid). 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; diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h index 6faf5a4ff..4ba6ee059 100644 --- a/libc/bionic/pthread_internal.h +++ b/libc/bionic/pthread_internal.h @@ -115,7 +115,7 @@ class pthread_internal_t { }; __LIBC_HIDDEN__ int __init_thread(pthread_internal_t* thread); -__LIBC_HIDDEN__ void __init_tls(pthread_internal_t* thread); +__LIBC_HIDDEN__ bool __init_tls(pthread_internal_t* thread); __LIBC_HIDDEN__ void __init_thread_stack_guard(pthread_internal_t* thread); __LIBC_HIDDEN__ void __init_alternate_signal_stack(pthread_internal_t*); diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp index d64bc48bc..bf6ed9a56 100755 --- a/tests/pthread_test.cpp +++ b/tests/pthread_test.cpp @@ -2076,3 +2076,49 @@ TEST(pthread, pthread_spinlock_smoke) { ASSERT_EQ(0, pthread_spin_unlock(&lock)); ASSERT_EQ(0, pthread_spin_destroy(&lock)); } + +TEST(pthread, pthread_attr_setdetachstate) { + pthread_attr_t attr; + ASSERT_EQ(0, pthread_attr_init(&attr)); + + ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)); + ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)); + ASSERT_EQ(EINVAL, pthread_attr_setdetachstate(&attr, 123)); +} + +TEST(pthread, pthread_create__mmap_failures) { + pthread_attr_t attr; + ASSERT_EQ(0, pthread_attr_init(&attr)); + ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)); + + const auto kPageSize = sysconf(_SC_PAGE_SIZE); + + // Use up all the VMAs. By default this is 64Ki. + std::vector<void*> pages; + int prot = PROT_NONE; + while (true) { + void* page = mmap(nullptr, kPageSize, prot, MAP_ANON|MAP_PRIVATE, -1, 0); + if (page == MAP_FAILED) break; + pages.push_back(page); + prot = (prot == PROT_NONE) ? PROT_READ : PROT_NONE; + } + + // Try creating threads, freeing up a page each time we fail. + size_t EAGAIN_count = 0; + size_t i = 0; + for (; i < pages.size(); ++i) { + pthread_t t; + int status = pthread_create(&t, &attr, IdFn, nullptr); + if (status != EAGAIN) break; + ++EAGAIN_count; + ASSERT_EQ(0, munmap(pages[i], kPageSize)); + } + + // Creating a thread uses at least six VMAs: the stack, the TLS, and a guard each side of both. + // So we should have seen at least six failures. + ASSERT_GE(EAGAIN_count, 6U); + + for (; i < pages.size(); ++i) { + ASSERT_EQ(0, munmap(pages[i], kPageSize)); + } +} |