Merge "Fix recursive deadlock inside bionic_systrace"
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 121b26f..08fb187 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -45,6 +45,7 @@
#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"
@@ -331,11 +332,9 @@
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
+__BIONIC_DISABLE_PAUTH
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 34efc48..c311651 100644
--- a/libc/platform/bionic/pac.h
+++ b/libc/platform/bionic/pac.h
@@ -29,6 +29,7 @@
#pragma once
#include <stddef.h>
+#include <sys/prctl.h>
inline uintptr_t __bionic_clear_pac_bits(uintptr_t ptr) {
#if defined(__aarch64__)
@@ -40,3 +41,39 @@
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 3ceafc7..dbefcf6 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -369,31 +369,9 @@
"liblinker_debuggerd_stub",
],
},
- android_arm64: {
- pgo: {
- profile_file: "bionic/linker_arm_arm64.profdata",
- },
- },
- android_arm: {
- pgo: {
- profile_file: "bionic/linker_arm_arm64.profdata",
- },
- },
- android_x86_64: {
- pgo: {
- profile_file: "bionic/linker_x86_x86_64.profdata",
- },
- },
- android_x86: {
- pgo: {
- profile_file: "bionic/linker_x86_x86_64.profdata",
- },
- },
},
- pgo: {
- sampling: true,
- },
+ afdo: true,
}
// ========================================================
diff --git a/tests/heap_tagging_level_test.cpp b/tests/heap_tagging_level_test.cpp
index edbd995..cfb2490 100644
--- a/tests/heap_tagging_level_test.cpp
+++ b/tests/heap_tagging_level_test.cpp
@@ -197,24 +197,33 @@
TEST_P(MemtagNoteTest, SEGV) {
#if defined(__BIONIC__) && defined(__aarch64__)
- if (!(getauxval(AT_HWCAP2) & HWCAP2_MTE)) {
- GTEST_SKIP() << "requires MTE support";
- }
+ // Note that we do not check running_with_hwasan() - what matters here is whether the test binary
+ // itself is built with HWASan.
+ bool withHWASAN = __has_feature(hwaddress_sanitizer);
+ bool withMTE = getauxval(AT_HWCAP2) & HWCAP2_MTE;
const char* kNoteSuffix[] = {"disabled", "async", "sync"};
- const char* kExpectedOutput[] = {"normal exit\n", "SEGV_MTEAERR\n", "SEGV_MTESERR\n"};
+ const char* kExpectedOutputHWASAN[] = {".*tag-mismatch.*", ".*tag-mismatch.*",
+ ".*tag-mismatch.*"};
+ const char* kExpectedOutputMTE[] = {"normal exit\n", "SEGV_MTEAERR\n", "SEGV_MTESERR\n"};
+ const char* kExpectedOutputNonMTE[] = {"normal exit\n", "normal exit\n", "normal exit\n"};
+ const char** kExpectedOutput =
+ withHWASAN ? kExpectedOutputHWASAN : (withMTE ? kExpectedOutputMTE : kExpectedOutputNonMTE);
+ const int kExpectedExitStatus = withHWASAN ? -SIGABRT : 0;
MemtagNote note = std::get<0>(GetParam());
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 + "/" + helper_base;
+ std::string helper = GetTestlibRoot() + "/" + helper_base;
chmod(helper.c_str(), 0755);
ExecTestHelper eth;
eth.SetArgs({helper.c_str(), nullptr});
- eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0,
+ eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, kExpectedExitStatus,
kExpectedOutput[static_cast<int>(note)]);
+#else
+ GTEST_SKIP() << "bionic/arm64 only";
#endif
}