diff options
Diffstat (limited to 'sigchainlib/sigchain_test.cc')
-rw-r--r-- | sigchainlib/sigchain_test.cc | 29 |
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 +} |