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();
 }