Merge "Support all architectures in seccomp"
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index f591c86..6b3e148 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -62,11 +62,13 @@
if (allocation == MAP_FAILED) {
__libc_fatal("failed to allocate TLS");
}
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, allocation, allocation_size, "bionic TLS guard page");
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) {
__libc_fatal("failed to mprotect TLS");
}
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, thread->bionic_tls, BIONIC_TLS_SIZE, "bionic TLS");
}
void __init_thread_stack_guard(pthread_internal_t* thread) {
diff --git a/libc/bionic/pthread_exit.cpp b/libc/bionic/pthread_exit.cpp
index 3401ed7..9adf405 100644
--- a/libc/bionic/pthread_exit.cpp
+++ b/libc/bionic/pthread_exit.cpp
@@ -92,6 +92,10 @@
thread->alternate_signal_stack = NULL;
}
+ // Unmap the bionic TLS, including guard pages.
+ void* allocation = reinterpret_cast<char*>(thread->bionic_tls) - PAGE_SIZE;
+ munmap(allocation, BIONIC_TLS_SIZE + 2 * PAGE_SIZE);
+
ThreadJoinState old_state = THREAD_NOT_JOINED;
while (old_state == THREAD_NOT_JOINED &&
!atomic_compare_exchange_weak(&thread->join_state, &old_state, THREAD_EXITED_NOT_JOINED)) {
diff --git a/libc/bionic/pthread_internal.cpp b/libc/bionic/pthread_internal.cpp
index 2bc2bfb..5819bc1 100644
--- a/libc/bionic/pthread_internal.cpp
+++ b/libc/bionic/pthread_internal.cpp
@@ -86,10 +86,6 @@
}
static void __pthread_internal_free(pthread_internal_t* thread) {
- // Unmap the TLS, including guard pages.
- void* allocation = reinterpret_cast<char*>(thread->bionic_tls) - PAGE_SIZE;
- munmap(allocation, BIONIC_TLS_SIZE + 2 * PAGE_SIZE);
-
if (thread->mmap_size != 0) {
// Free mapped space, including thread stack and pthread_internal_t.
munmap(thread->attr.stack_base, thread->mmap_size);
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index b170299..6faf5a4 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -141,13 +141,11 @@
__LIBC_HIDDEN__ void pthread_key_clean_all(void);
-#if defined(__LP64__)
-// SIGSTKSZ is not big enough for 64-bit arch.
-// See https://code.google.com/p/android/issues/detail?id=187064.
+// SIGSTKSZ (8kB) is not big enough.
+// snprintf to a stack buffer of size PATH_MAX consumes ~7kB of stack.
+// Also, on 64-bit, logging uses more than 8kB by itself:
+// https://code.google.com/p/android/issues/detail?id=187064
#define SIGNAL_STACK_SIZE_WITHOUT_GUARD_PAGE (16 * 1024)
-#else
-#define SIGNAL_STACK_SIZE_WITHOUT_GUARD_PAGE SIGSTKSZ
-#endif
/*
* Traditionally we gave threads a 1MiB stack. When we started
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
index 2bbf2d3..a4faf85 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -1058,15 +1058,23 @@
return true;
}
- // TODO: Change path to /system/property_contexts after b/27805372
- if (!initialize_properties_from_file("/plat_property_contexts")) {
- return false;
+ // Use property_contexts from /system & /vendor, fall back to those from /
+ if (access("/system/etc/selinux/plat_property_contexts", R_OK) != -1) {
+ if (!initialize_properties_from_file("/system/etc/selinux/plat_property_contexts")) {
+ return false;
+ }
+ if (!initialize_properties_from_file("/vendor/etc/selinux/nonplat_property_contexts")) {
+ return false;
+ }
+ } else {
+ if (!initialize_properties_from_file("/plat_property_contexts")) {
+ return false;
+ }
+ if (!initialize_properties_from_file("/nonplat_property_contexts")) {
+ return false;
+ }
}
- // TODO: Change path to /vendor/property_contexts after b/27805372
- // device-specific property context is optional, so load if it exists.
- initialize_properties_from_file("/nonplat_property_contexts");
-
return true;
}
diff --git a/libc/malloc_debug/README_api.md b/libc/malloc_debug/README_api.md
index 9d07cb3..b2c46d8 100644
--- a/libc/malloc_debug/README_api.md
+++ b/libc/malloc_debug/README_api.md
@@ -26,7 +26,7 @@
### Format of info Buffer
size_t size_of_original_allocation
- size_t num_backtrace_frames
+ size_t num_allocations
uintptr_t pc1
uintptr_t pc2
uintptr_t pc3
@@ -38,8 +38,12 @@
*backtrace\_size* as returned by the original call to
*get\_malloc\_leak\_info*. This value is not variable, it is the same
for all the returned data. The value
-*num\_backtrace\_frames* contains the real number of frames found. The
-extra frames are set to zero. Each *uintptr\_t* is a pc of the callstack.
+*num\_allocations* contains the total number of allocations with the same
+backtrace and size as this allocation. On Android Nougat, this value was
+incorrectly set to the number of frames in the backtrace.
+Each *uintptr\_t* is a pc of the callstack. If the total number
+of backtrace entries is less than *backtrace\_size*, the rest of the
+entries are zero.
The calls from within the malloc debug library are automatically removed.
For 32 bit systems, *size\_t* and *uintptr\_t* are both 4 byte values.
diff --git a/libc/malloc_debug/TrackData.cpp b/libc/malloc_debug/TrackData.cpp
index 18f428b..d4064f8 100644
--- a/libc/malloc_debug/TrackData.cpp
+++ b/libc/malloc_debug/TrackData.cpp
@@ -123,11 +123,12 @@
GetList(&list);
uint8_t* data = *info;
+ size_t num_allocations = 1;
for (const auto& header : list) {
BacktraceHeader* back_header = debug_->GetAllocBacktrace(header);
if (back_header->num_frames > 0) {
memcpy(data, &header->size, sizeof(size_t));
- memcpy(&data[sizeof(size_t)], &back_header->num_frames, sizeof(size_t));
+ memcpy(&data[sizeof(size_t)], &num_allocations, sizeof(size_t));
memcpy(&data[2 * sizeof(size_t)], &back_header->frames[0],
back_header->num_frames * sizeof(uintptr_t));
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 1b08a39..219c21e 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -999,7 +999,7 @@
struct InfoEntry {
size_t size;
- size_t num_frames;
+ size_t num_allocations;
uintptr_t frames[0];
} __attribute__((packed));
@@ -1033,7 +1033,7 @@
InfoEntry* entry = reinterpret_cast<InfoEntry*>(expected_info.data());
entry->size = 200;
- entry->num_frames = 3;
+ entry->num_allocations = 1;
entry->frames[0] = 0xf;
entry->frames[1] = 0xe;
entry->frames[2] = 0xd;
@@ -1082,7 +1082,7 @@
// These values will be in the reverse order that we create.
entry2->size = 500;
- entry2->num_frames = 4;
+ entry2->num_allocations = 1;
entry2->frames[0] = 0xf;
entry2->frames[1] = 0xe;
entry2->frames[2] = 0xd;
@@ -1097,7 +1097,7 @@
memset(pointers[0], 0, entry2->size);
entry1->size = 4100;
- entry1->num_frames = 16;
+ entry1->num_allocations = 1;
for (size_t i = 0; i < 16; i++) {
entry1->frames[i] = 0xbc000 + i;
}
@@ -1112,7 +1112,7 @@
memset(pointers[1], 0, entry1->size);
entry0->size = 9000;
- entry0->num_frames = 1;
+ entry0->num_allocations = 1;
entry0->frames[0] = 0x104;
backtrace_fake_add(std::vector<uintptr_t> {0x104});
@@ -1159,7 +1159,7 @@
// These values will be in the reverse order that we create.
entry1->size = 500;
- entry1->num_frames = 4;
+ entry1->num_allocations = 1;
entry1->frames[0] = 0xf;
entry1->frames[1] = 0xe;
entry1->frames[2] = 0xd;
@@ -1174,7 +1174,7 @@
memset(pointers[0], 0, entry1->size);
entry0->size = 4100;
- entry0->num_frames = 16;
+ entry0->num_allocations = 1;
for (size_t i = 0; i < 16; i++) {
entry0->frames[i] = 0xbc000 + i;
}
@@ -1373,7 +1373,7 @@
memset(expected_info.data(), 0, expected_info_size);
InfoEntry* entry = reinterpret_cast<InfoEntry*>(expected_info.data());
entry->size = memory_bytes | (1U << 31);
- entry->num_frames = 1;
+ entry->num_allocations = 1;
entry->frames[0] = 0x1;
uint8_t* info;
diff --git a/linker/linker.cpp b/linker/linker.cpp
index d7864b4..846cb88 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1889,14 +1889,16 @@
if (g_is_asan && translated_name != nullptr && translated_name[0] == '/') {
char translated_path[PATH_MAX];
if (realpath(translated_name, translated_path) != nullptr) {
- if (file_is_in_dir(translated_path, kSystemLibDir)) {
- asan_name_holder = std::string(kAsanSystemLibDir) + "/" + basename(translated_path);
+ if (file_is_under_dir(translated_path, kSystemLibDir)) {
+ asan_name_holder = std::string(kAsanSystemLibDir) + "/" +
+ (translated_path + strlen(kSystemLibDir) + 1);
if (file_exists(asan_name_holder.c_str())) {
translated_name = asan_name_holder.c_str();
PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
}
- } else if (file_is_in_dir(translated_path, kVendorLibDir)) {
- asan_name_holder = std::string(kAsanVendorLibDir) + "/" + basename(translated_path);
+ } else if (file_is_under_dir(translated_path, kVendorLibDir)) {
+ asan_name_holder = std::string(kAsanVendorLibDir) + "/" +
+ (translated_path + strlen(kVendorLibDir) + 1);
if (file_exists(asan_name_holder.c_str())) {
translated_name = asan_name_holder.c_str();
PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
diff --git a/linker/linker_memory.cpp b/linker/linker_memory.cpp
index 18ef93e..f8852e1 100644
--- a/linker/linker_memory.cpp
+++ b/linker/linker_memory.cpp
@@ -39,16 +39,22 @@
// Used by libdebuggerd_handler to switch allocators during a crash dump, in
// case the linker heap is corrupted. Do not use this function.
-extern "C" void __linker_use_fallback_allocator() {
+extern "C" void __linker_enable_fallback_allocator() {
if (fallback_tid != 0) {
- __libc_format_log(ANDROID_LOG_ERROR, "libc",
- "attempted to set fallback allocator multiple times");
- return;
+ __libc_fatal("attempted to use currently-in-use fallback allocator");
}
fallback_tid = gettid();
}
+extern "C" void __linker_disable_fallback_allocator() {
+ if (fallback_tid == 0) {
+ __libc_fatal("attempted to disable unused fallback allocator");
+ }
+
+ fallback_tid = 0;
+}
+
static LinkerMemoryAllocator& get_fallback_allocator() {
static LinkerMemoryAllocator fallback_allocator;
return fallback_allocator;
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 024a675..4fb15ad 100755
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -1888,17 +1888,26 @@
static void SignalHandlerOnAltStack(int signo, siginfo_t*, void*) {
ASSERT_EQ(SIGUSR1, signo);
- // Check if we have enough stack space for unwinding.
- int count = 0;
- _Unwind_Backtrace(FrameCounter, &count);
- ASSERT_GT(count, 0);
- // Check if we have enough stack space for logging.
- std::string s(2048, '*');
- GTEST_LOG_(INFO) << s;
- signal_handler_on_altstack_done = true;
+ {
+ // Check if we have enough stack space for unwinding.
+ int count = 0;
+ _Unwind_Backtrace(FrameCounter, &count);
+ ASSERT_GT(count, 0);
+ }
+ {
+ // Check if we have enough stack space for logging.
+ std::string s(2048, '*');
+ GTEST_LOG_(INFO) << s;
+ signal_handler_on_altstack_done = true;
+ }
+ {
+ // Check if we have enough stack space for snprintf to a PATH_MAX buffer, plus some extra.
+ char buf[PATH_MAX + 2048];
+ ASSERT_GT(snprintf(buf, sizeof(buf), "/proc/%d/status", getpid()), 0);
+ }
}
-TEST(pthread, big_enough_signal_stack_for_64bit_arch) {
+TEST(pthread, big_enough_signal_stack) {
signal_handler_on_altstack_done = false;
ScopedSignalHandler handler(SIGUSR1, SignalHandlerOnAltStack, SA_SIGINFO | SA_ONSTACK);
kill(getpid(), SIGUSR1);