Merge "Suppress -Wformat warning"
diff --git a/benchmarks/spawn/Android.bp b/benchmarks/spawn/Android.bp
index 89d22e3..61e7bf6 100644
--- a/benchmarks/spawn/Android.bp
+++ b/benchmarks/spawn/Android.bp
@@ -43,6 +43,9 @@
         linux_glibc_x86: {
             enabled: false,
         },
+        linux_musl_x86: {
+            enabled: false,
+        },
     },
 }
 
@@ -103,6 +106,11 @@
                 "-Wl,--rpath,${ORIGIN}/../../lib64",
             ],
         },
+        linux_musl_x86_64: {
+            ldflags: [
+                "-Wl,--rpath,${ORIGIN}/../../lib64",
+            ],
+        },
     },
 }
 
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 08fb187..121b26f 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -45,7 +45,6 @@
 #include "private/bionic_defs.h"
 #include "private/bionic_globals.h"
 #include "platform/bionic/macros.h"
-#include "platform/bionic/pac.h"
 #include "private/bionic_ssp.h"
 #include "private/bionic_systrace.h"
 #include "private/bionic_tls.h"
@@ -332,9 +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.
-__BIONIC_DISABLE_PAUTH
+__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/platform/bionic/pac.h b/libc/platform/bionic/pac.h
index c311651..34efc48 100644
--- a/libc/platform/bionic/pac.h
+++ b/libc/platform/bionic/pac.h
@@ -29,7 +29,6 @@
 #pragma once
 
 #include <stddef.h>
-#include <sys/prctl.h>
 
 inline uintptr_t __bionic_clear_pac_bits(uintptr_t ptr) {
 #if defined(__aarch64__)
@@ -41,39 +40,3 @@
   return ptr;
 #endif
 }
-
-#ifdef __aarch64__
-// The default setting for branch-protection enables both PAC and BTI, so by
-// overriding it to only enable BTI we disable PAC.
-#define __BIONIC_DISABLE_PAUTH __attribute__((target("branch-protection=bti")))
-#else
-#define __BIONIC_DISABLE_PAUTH
-#endif
-
-#ifdef __aarch64__
-// Disable PAC (i.e. make the signing and authentication instructions into no-ops) for the lifetime
-// of this object.
-class ScopedDisablePAC {
-  int prev_enabled_keys_;
-
- public:
-  // Disabling IA will invalidate the return address in this function if it is signed, so we need to
-  // make sure that this function does not sign its return address. Likewise for the destructor.
-  __BIONIC_DISABLE_PAUTH
-  ScopedDisablePAC() {
-    // These prctls will fail (resulting in a no-op, the intended behavior) if PAC is not supported.
-    prev_enabled_keys_ = prctl(PR_PAC_GET_ENABLED_KEYS, 0, 0, 0, 0);
-    prctl(PR_PAC_SET_ENABLED_KEYS, prev_enabled_keys_, 0, 0, 0);
-  }
-
-  __BIONIC_DISABLE_PAUTH
-  ~ScopedDisablePAC() {
-    prctl(PR_PAC_SET_ENABLED_KEYS, prev_enabled_keys_, prev_enabled_keys_, 0, 0);
-  }
-};
-#else
-struct ScopedDisablePAC {
-  // Silence unused variable warnings in non-aarch64 builds.
-  ScopedDisablePAC() {}
-};
-#endif
diff --git a/linker/Android.bp b/linker/Android.bp
index dbefcf6..d5e7367 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -28,16 +28,11 @@
     name: "linker_wrapper",
     host_supported: true,
     device_supported: false,
+    enabled: false,
     target: {
         linux_bionic: {
             enabled: true,
         },
-        linux_glibc: {
-            enabled: false,
-        },
-        darwin: {
-            enabled: false,
-        },
     },
 
     cflags: [
diff --git a/tests/heap_tagging_level_test.cpp b/tests/heap_tagging_level_test.cpp
index cfb2490..c493e1d 100644
--- a/tests/heap_tagging_level_test.cpp
+++ b/tests/heap_tagging_level_test.cpp
@@ -81,10 +81,20 @@
 #endif // defined(__BIONIC__)
 }
 
+namespace {
 #if defined(__BIONIC__) && defined(__aarch64__)
 void ExitWithSiCode(int, siginfo_t* info, void*) {
   _exit(info->si_code);
 }
+
+template <typename Pred>
+class Or {
+  Pred A, B;
+
+ public:
+  Or(Pred A, Pred B) : A(A), B(B) {}
+  bool operator()(int exit_status) { return A(exit_status) || B(exit_status); }
+};
 #endif
 
 TEST(heap_tagging_level, sync_async_bad_accesses_die) {
@@ -94,6 +104,7 @@
   }
 
   std::unique_ptr<int[]> p = std::make_unique<int[]>(4);
+  volatile int sink ATTRIBUTE_UNUSED;
 
   // We assume that scudo is used on all MTE enabled hardware; scudo inserts a header with a
   // mismatching tag before each allocation.
@@ -104,6 +115,12 @@
         p[-1] = 42;
       },
       testing::ExitedWithCode(SEGV_MTESERR), "");
+  EXPECT_EXIT(
+      {
+        ScopedSignalHandler ssh(SIGSEGV, ExitWithSiCode, SA_SIGINFO);
+        sink = p[-1];
+      },
+      testing::ExitedWithCode(SEGV_MTESERR), "");
 
   EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_ASYNC));
   EXPECT_EXIT(
@@ -111,14 +128,21 @@
         ScopedSignalHandler ssh(SIGSEGV, ExitWithSiCode, SA_SIGINFO);
         p[-1] = 42;
       },
-      testing::ExitedWithCode(SEGV_MTEAERR), "");
+      Or(testing::ExitedWithCode(SEGV_MTESERR), testing::ExitedWithCode(SEGV_MTEAERR)), "");
+  EXPECT_EXIT(
+      {
+        ScopedSignalHandler ssh(SIGSEGV, ExitWithSiCode, SA_SIGINFO);
+        sink = p[-1];
+      },
+      Or(testing::ExitedWithCode(SEGV_MTESERR), testing::ExitedWithCode(SEGV_MTEAERR)), "");
 
   EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_NONE));
-  volatile int oob ATTRIBUTE_UNUSED = p[-1];
+  sink = p[-1];
 #else
   GTEST_SKIP() << "bionic/arm64 only";
 #endif
 }
+}  // namespace
 
 TEST(heap_tagging_level, none_pointers_untagged) {
 #if defined(__BIONIC__)
@@ -205,7 +229,9 @@
   const char* kNoteSuffix[] = {"disabled", "async", "sync"};
   const char* kExpectedOutputHWASAN[] = {".*tag-mismatch.*", ".*tag-mismatch.*",
                                          ".*tag-mismatch.*"};
-  const char* kExpectedOutputMTE[] = {"normal exit\n", "SEGV_MTEAERR\n", "SEGV_MTESERR\n"};
+  // Note that we do not check the exact si_code of the "async" variant, as it may be auto-upgraded
+  // to asymm or even sync.
+  const char* kExpectedOutputMTE[] = {"normal exit\n", "SEGV_MTE[AS]ERR\n", "SEGV_MTESERR\n"};
   const char* kExpectedOutputNonMTE[] = {"normal exit\n", "normal exit\n", "normal exit\n"};
   const char** kExpectedOutput =
       withHWASAN ? kExpectedOutputHWASAN : (withMTE ? kExpectedOutputMTE : kExpectedOutputNonMTE);
@@ -215,7 +241,6 @@
   bool isStatic = std::get<1>(GetParam());
   std::string helper_base = std::string("heap_tagging_") + (isStatic ? "static_" : "") +
                             kNoteSuffix[static_cast<int>(note)] + "_helper";
-  fprintf(stderr, "=== %s\n", helper_base.c_str());
   std::string helper = GetTestlibRoot() + "/" + helper_base;
   chmod(helper.c_str(), 0755);
   ExecTestHelper eth;
diff --git a/tests/libs/heap_tagging_helper.cpp b/tests/libs/heap_tagging_helper.cpp
index 1a970f2..16a8c8b 100644
--- a/tests/libs/heap_tagging_helper.cpp
+++ b/tests/libs/heap_tagging_helper.cpp
@@ -16,7 +16,9 @@
 
 #include <signal.h>
 #include <stdio.h>
+#include <sys/auxv.h>
 #include <sys/cdefs.h>
+#include <sys/mman.h>
 #include <unistd.h>
 #include <memory>
 
@@ -37,6 +39,11 @@
   _exit(0);
 }
 
+void action2(int signo, siginfo_t* info __unused, void*) {
+  fprintf(stderr, "unexpected signal %d\n", signo);
+  _exit(0);
+}
+
 __attribute__((optnone)) int main() {
   struct sigaction sa = {};
   sa.sa_sigaction = action;
@@ -47,6 +54,37 @@
   volatile int oob = p[-1];
   (void)oob;
 
+#if defined(__BIONIC__) && defined(__aarch64__)
+  // If we get here, bad access on system heap memory did not trigger a fault.
+  // This suggests that MTE is disabled. Make sure that explicitly tagged PROT_MTE memory does not
+  // trigger a fault either.
+  if (getauxval(AT_HWCAP2) & HWCAP2_MTE) {
+    sa.sa_sigaction = action2;
+    sigaction(SIGSEGV, &sa, nullptr);
+
+    size_t page_size = static_cast<size_t>(sysconf(_SC_PAGESIZE));
+    void* p = mmap(nullptr, page_size, PROT_READ | PROT_WRITE | PROT_MTE,
+                   MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+    if (!p) {
+      fprintf(stderr, "mmap failed\n");
+      return 1;
+    }
+
+    void* q = p;
+    __asm__ __volatile__(
+        ".arch_extension memtag\n"
+        "irg %[Ptr], %[Ptr], xzr\n"
+        "stg %[Ptr], [%[Ptr]]\n"
+        "addg %[Ptr], %[Ptr], 0, 1\n"
+        "str xzr, [%[Ptr]]\n"
+        : [Ptr] "+&r"(q)
+        :
+        : "memory");
+
+    munmap(p, page_size);
+  }
+#endif  // __aarch64__
+
   fprintf(stderr, "normal exit\n");
   return 0;
 }