summaryrefslogtreecommitdiff
path: root/sigchainlib/sigchain_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sigchainlib/sigchain_test.cc')
-rw-r--r--sigchainlib/sigchain_test.cc29
1 files changed, 29 insertions, 0 deletions
diff --git a/sigchainlib/sigchain_test.cc b/sigchainlib/sigchain_test.cc
index bb997877a1..4ef98c2b8f 100644
--- a/sigchainlib/sigchain_test.cc
+++ b/sigchainlib/sigchain_test.cc
@@ -238,3 +238,32 @@ TEST_F(SigchainTest, EnsureFrontOfChain) {
ASSERT_EQ(1, called);
called = 0;
}
+
+TEST_F(SigchainTest, fault_address_tag) {
+#define SA_EXPOSE_TAGBITS 0x00000800
+#if defined(__aarch64__)
+ struct sigaction action = {};
+ action.sa_flags = SA_SIGINFO;
+ action.sa_sigaction = [](int, siginfo_t* siginfo, void*) {
+ _exit(reinterpret_cast<uintptr_t>(siginfo->si_addr) >> 56);
+ };
+ ASSERT_EQ(0, sigaction(SIGSEGV, &action, nullptr));
+
+ auto* tagged_null = reinterpret_cast<int*>(0x2bULL << 56);
+ EXPECT_EXIT({ volatile int load __attribute__((unused)) = *tagged_null; },
+ testing::ExitedWithCode(0), "");
+
+ // Our sigaction implementation always implements the "clear unknown bits"
+ // semantics for oldact.sa_flags regardless of kernel version so we rely on it
+ // here to test for kernel support for SA_EXPOSE_TAGBITS.
+ action.sa_flags = SA_SIGINFO | SA_EXPOSE_TAGBITS;
+ ASSERT_EQ(0, sigaction(SIGSEGV, &action, nullptr));
+ ASSERT_EQ(0, sigaction(SIGSEGV, nullptr, &action));
+ if (action.sa_flags & SA_EXPOSE_TAGBITS) {
+ EXPECT_EXIT({ volatile int load __attribute__((unused)) = *tagged_null; },
+ testing::ExitedWithCode(0x2b), "");
+ }
+#else
+ GTEST_SKIP() << "arm64 only";
+#endif
+}