Merge "Allow the kernel to upgrade ASYNC mode processes to SYNC mode." into sc-dev
diff --git a/apex/Android.bp b/apex/Android.bp
index 90a14b2..4879f47 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -58,6 +58,7 @@
"bionic-linker-config",
],
updatable: false,
+ generate_hashtree: false,
}
sdk {
diff --git a/libc/bionic/malloc_heapprofd.cpp b/libc/bionic/malloc_heapprofd.cpp
index 198bcba..741b45e 100644
--- a/libc/bionic/malloc_heapprofd.cpp
+++ b/libc/bionic/malloc_heapprofd.cpp
@@ -325,12 +325,12 @@
static void CommonInstallHooks(libc_globals* globals) {
void* impl_handle = atomic_load(&gHeapprofdHandle);
- bool reusing_handle = impl_handle != nullptr;
- if (!reusing_handle) {
+ if (impl_handle == nullptr) {
impl_handle = LoadSharedLibrary(kHeapprofdSharedLib, kHeapprofdPrefix, &globals->malloc_dispatch_table);
if (impl_handle == nullptr) {
return;
}
+ atomic_store(&gHeapprofdHandle, impl_handle);
} else if (!InitSharedLibrary(impl_handle, kHeapprofdSharedLib, kHeapprofdPrefix, &globals->malloc_dispatch_table)) {
return;
}
@@ -341,11 +341,7 @@
// MaybeModifyGlobals locks at this point.
atomic_store(&gPreviousDefaultDispatchTable, GetDefaultDispatchTable());
- if (FinishInstallHooks(globals, nullptr, kHeapprofdPrefix)) {
- atomic_store(&gHeapprofdHandle, impl_handle);
- } else if (!reusing_handle) {
- dlclose(impl_handle);
- }
+ FinishInstallHooks(globals, nullptr, kHeapprofdPrefix);
}
void HeapprofdInstallHooksAtInit(libc_globals* globals) {
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 46d9e86..121b26f 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -331,6 +331,11 @@
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);
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index bae1f68..f7beb2c 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -170,7 +170,45 @@
* Available since API level 28.
*/
#define M_PURGE (-101)
-/*
+
+
+/**
+ * mallopt() option to tune the allocator's choice of memory tags to
+ * make it more likely that a certain class of memory errors will be
+ * detected. This is only relevant if MTE is enabled in this process
+ * and ignored otherwise. The value argument should be one of the
+ * M_MEMTAG_TUNING_* flags.
+ * NOTE: This is only available in scudo.
+ *
+ * Available since API level 31.
+ */
+#define M_MEMTAG_TUNING (-102)
+
+/**
+ * When passed as a value of M_MEMTAG_TUNING mallopt() call, enables
+ * deterministic detection of linear buffer overflow and underflow
+ * bugs by assigning distinct tag values to adjacent allocations. This
+ * mode has a slightly reduced chance to detect use-after-free bugs
+ * because only half of the possible tag values are available for each
+ * memory location.
+ *
+ * Please keep in mind that MTE can not detect overflow within the
+ * same tag granule (16-byte aligned chunk), and can miss small
+ * overflows even in this mode. Such overflow can not be the cause of
+ * a memory corruption, because the memory within one granule is never
+ * used for multiple allocations.
+ */
+#define M_MEMTAG_TUNING_BUFFER_OVERFLOW 0
+
+/**
+ * When passed as a value of M_MEMTAG_TUNING mallopt() call, enables
+ * independently randomized tags for uniform ~93% probability of
+ * detecting both spatial (buffer overflow) and temporal (use after
+ * free) bugs.
+ */
+#define M_MEMTAG_TUNING_UAF 1
+
+/**
* mallopt() option for per-thread memory initialization tuning.
* The value argument should be one of:
* 1: Disable automatic heap initialization and, where possible, memory tagging,
@@ -210,7 +248,7 @@
* should not be zero-initialized, any other value indicates to initialize heap
* memory to zero.
*
- * Note that this memory mitigations is only implemented in scudo and therefore
+ * Note that this memory mitigation is only implemented in scudo and therefore
* this will have no effect when using another allocator (such as jemalloc on
* Android Go devices).
*
@@ -222,6 +260,7 @@
* mallopt() option to change the heap tagging state. May be called at any
* time, including when multiple threads are running.
* The value must be one of the M_HEAP_TAGGING_LEVEL_ constants.
+ * NOTE: This is only available in scudo.
*
* Available since API level 31.
*/
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index 766f27a..47bf133 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -264,8 +264,11 @@
#endif
#if defined(__BIONIC__)
-static bool is_debuggable_build() {
- return android::base::GetBoolProperty("ro.debuggable", false);
+// This test can't rely on ro.debuggable, because it might have been forced on
+// in a user build ("Force Debuggable"). In that configuration, ro.debuggable is
+// true, but Bionic's LD_CONFIG_FILE testing support is still disabled.
+static bool is_user_build() {
+ return android::base::GetProperty("ro.build.type", "user") == std::string("user");
}
#endif
@@ -282,7 +285,7 @@
TEST(dl, exec_with_ld_config_file) {
#if defined(__BIONIC__)
SKIP_WITH_HWASAN << "libclang_rt.hwasan is not found with custom ld config";
- if (!is_debuggable_build()) {
+ if (is_user_build()) {
GTEST_SKIP() << "LD_CONFIG_FILE is not supported on user build";
}
std::string helper = GetTestlibRoot() +
@@ -319,7 +322,7 @@
TEST(dl, exec_with_ld_config_file_with_ld_preload) {
#if defined(__BIONIC__)
SKIP_WITH_HWASAN << "libclang_rt.hwasan is not found with custom ld config";
- if (!is_debuggable_build()) {
+ if (is_user_build()) {
GTEST_SKIP() << "LD_CONFIG_FILE is not supported on user build";
}
std::string helper = GetTestlibRoot() +
@@ -356,8 +359,8 @@
// This test is only for CTS.
GTEST_SKIP() << "test is not supported with root uid";
}
- if (is_debuggable_build()) {
- GTEST_SKIP() << "test is not supported on debuggable build";
+ if (!is_user_build()) {
+ GTEST_SKIP() << "test requires user build";
}
std::string error_message = std::string("CANNOT LINK EXECUTABLE ") +
diff --git a/tests/stack_unwinding_test.cpp b/tests/stack_unwinding_test.cpp
index 0ff6f30..2f891a6 100644
--- a/tests/stack_unwinding_test.cpp
+++ b/tests/stack_unwinding_test.cpp
@@ -66,13 +66,28 @@
return count;
}
-TEST(stack_unwinding, easy) {
+static void UnwindTest() {
int count = 0;
_Unwind_Backtrace(FrameCounter, &count);
int deeper_count = unwind_one_frame_deeper();
ASSERT_EQ(count + 1, deeper_count);
}
+TEST(stack_unwinding, easy) {
+ UnwindTest();
+}
+
+TEST(stack_unwinding, thread) {
+ pthread_t thread;
+ ASSERT_EQ(0, pthread_create(&thread, nullptr, [](void*) -> void* {
+ UnwindTest();
+ return nullptr;
+ }, nullptr));
+ void *retval;
+ ASSERT_EQ(0, pthread_join(thread, &retval));
+ EXPECT_EQ(nullptr, retval);
+}
+
struct UnwindData {
volatile bool signal_handler_complete = false;
int expected_frame_count = 0;
@@ -98,7 +113,7 @@
EXPECT_EQ(unwind_data.handler_frame_count + 1, unwind_data.handler_one_deeper_frame_count);
}
-static void noinline UnwindTest() {
+static void noinline SignalUnwindTest() {
g_unwind_data = {};
_Unwind_Backtrace(FrameCounter, &g_unwind_data.expected_frame_count);
@@ -114,12 +129,12 @@
TEST(stack_unwinding, unwind_through_signal_frame) {
ScopedSignalHandler ssh(SIGUSR1, UnwindSignalHandler);
- UnwindTest();
+ SignalUnwindTest();
}
// On LP32, the SA_SIGINFO flag gets you __restore_rt instead of __restore.
TEST(stack_unwinding, unwind_through_signal_frame_SA_SIGINFO) {
ScopedSignalHandler ssh(SIGUSR1, UnwindSignalHandler, SA_SIGINFO);
- UnwindTest();
+ SignalUnwindTest();
}