xref: /aosp_15_r20/art/sigchainlib/sigchain_test.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  * All rights reserved.
4*795d594fSAndroid Build Coastguard Worker  *
5*795d594fSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
6*795d594fSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
7*795d594fSAndroid Build Coastguard Worker  * are met:
8*795d594fSAndroid Build Coastguard Worker  *  * Redistributions of source code must retain the above copyright
9*795d594fSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
10*795d594fSAndroid Build Coastguard Worker  *  * Redistributions in binary form must reproduce the above copyright
11*795d594fSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in
12*795d594fSAndroid Build Coastguard Worker  *    the documentation and/or other materials provided with the
13*795d594fSAndroid Build Coastguard Worker  *    distribution.
14*795d594fSAndroid Build Coastguard Worker  *
15*795d594fSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16*795d594fSAndroid Build Coastguard Worker  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17*795d594fSAndroid Build Coastguard Worker  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18*795d594fSAndroid Build Coastguard Worker  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19*795d594fSAndroid Build Coastguard Worker  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20*795d594fSAndroid Build Coastguard Worker  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21*795d594fSAndroid Build Coastguard Worker  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22*795d594fSAndroid Build Coastguard Worker  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23*795d594fSAndroid Build Coastguard Worker  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*795d594fSAndroid Build Coastguard Worker  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25*795d594fSAndroid Build Coastguard Worker  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*795d594fSAndroid Build Coastguard Worker  * SUCH DAMAGE.
27*795d594fSAndroid Build Coastguard Worker  */
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker #include <dlfcn.h>
30*795d594fSAndroid Build Coastguard Worker #include <pthread.h>
31*795d594fSAndroid Build Coastguard Worker #include <signal.h>
32*795d594fSAndroid Build Coastguard Worker #include <sys/syscall.h>
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker #include <functional>
35*795d594fSAndroid Build Coastguard Worker 
36*795d594fSAndroid Build Coastguard Worker #include <gtest/gtest.h>
37*795d594fSAndroid Build Coastguard Worker 
38*795d594fSAndroid Build Coastguard Worker #include "sigchain.h"
39*795d594fSAndroid Build Coastguard Worker 
40*795d594fSAndroid Build Coastguard Worker #if defined(__clang__) && __has_feature(hwaddress_sanitizer)
41*795d594fSAndroid Build Coastguard Worker #define DISABLE_HWASAN __attribute__((no_sanitize("hwaddress")))
42*795d594fSAndroid Build Coastguard Worker #else
43*795d594fSAndroid Build Coastguard Worker #define DISABLE_HWASAN
44*795d594fSAndroid Build Coastguard Worker #endif
45*795d594fSAndroid Build Coastguard Worker 
46*795d594fSAndroid Build Coastguard Worker #if !defined(__BIONIC__)
47*795d594fSAndroid Build Coastguard Worker using sigset64_t = sigset_t;
48*795d594fSAndroid Build Coastguard Worker 
sigemptyset64(sigset64_t * set)49*795d594fSAndroid Build Coastguard Worker static int sigemptyset64(sigset64_t* set) {
50*795d594fSAndroid Build Coastguard Worker   return sigemptyset(set);
51*795d594fSAndroid Build Coastguard Worker }
52*795d594fSAndroid Build Coastguard Worker 
sigismember64(sigset64_t * set,int member)53*795d594fSAndroid Build Coastguard Worker static int sigismember64(sigset64_t* set, int member) {
54*795d594fSAndroid Build Coastguard Worker   return sigismember(set, member);
55*795d594fSAndroid Build Coastguard Worker }
56*795d594fSAndroid Build Coastguard Worker #endif
57*795d594fSAndroid Build Coastguard Worker 
RealSigprocmask(int how,const sigset64_t * new_sigset,sigset64_t * old_sigset)58*795d594fSAndroid Build Coastguard Worker static int RealSigprocmask(int how, const sigset64_t* new_sigset, sigset64_t* old_sigset) {
59*795d594fSAndroid Build Coastguard Worker   // glibc's sigset_t is overly large, so sizeof(*new_sigset) doesn't work.
60*795d594fSAndroid Build Coastguard Worker   return syscall(__NR_rt_sigprocmask, how, new_sigset, old_sigset, NSIG/8);
61*795d594fSAndroid Build Coastguard Worker }
62*795d594fSAndroid Build Coastguard Worker 
63*795d594fSAndroid Build Coastguard Worker class SigchainTest : public ::testing::Test {
SetUp()64*795d594fSAndroid Build Coastguard Worker   void SetUp() final {
65*795d594fSAndroid Build Coastguard Worker     art::AddSpecialSignalHandlerFn(SIGSEGV, &action);
66*795d594fSAndroid Build Coastguard Worker   }
67*795d594fSAndroid Build Coastguard Worker 
TearDown()68*795d594fSAndroid Build Coastguard Worker   void TearDown() final {
69*795d594fSAndroid Build Coastguard Worker     art::RemoveSpecialSignalHandlerFn(SIGSEGV, action.sc_sigaction);
70*795d594fSAndroid Build Coastguard Worker   }
71*795d594fSAndroid Build Coastguard Worker 
72*795d594fSAndroid Build Coastguard Worker   art::SigchainAction action = {
__anon4261b3b00102() 73*795d594fSAndroid Build Coastguard Worker       .sc_sigaction = [](int, siginfo_t* info, void*) -> bool {
74*795d594fSAndroid Build Coastguard Worker         return info->si_value.sival_ptr;
75*795d594fSAndroid Build Coastguard Worker       },
__anon4261b3b00202() 76*795d594fSAndroid Build Coastguard Worker       .sc_mask = {},
77*795d594fSAndroid Build Coastguard Worker       .sc_flags = 0,
78*795d594fSAndroid Build Coastguard Worker   };
79*795d594fSAndroid Build Coastguard Worker 
80*795d594fSAndroid Build Coastguard Worker  protected:
RaiseHandled()81*795d594fSAndroid Build Coastguard Worker   void RaiseHandled() {
82*795d594fSAndroid Build Coastguard Worker       sigval value;
83*795d594fSAndroid Build Coastguard Worker       value.sival_ptr = &value;
84*795d594fSAndroid Build Coastguard Worker       // pthread_sigqueue would guarantee the signal is delivered to this
85*795d594fSAndroid Build Coastguard Worker       // thread, but it is a nonstandard extension and does not exist in
86*795d594fSAndroid Build Coastguard Worker       // musl.  Gtest is single threaded, and these tests don't create any
87*795d594fSAndroid Build Coastguard Worker       // threads, so sigqueue can be used and will deliver to this thread.
88*795d594fSAndroid Build Coastguard Worker       sigqueue(getpid(), SIGSEGV, value);
89*795d594fSAndroid Build Coastguard Worker   }
90*795d594fSAndroid Build Coastguard Worker 
RaiseUnhandled()91*795d594fSAndroid Build Coastguard Worker   void RaiseUnhandled() {
92*795d594fSAndroid Build Coastguard Worker       sigval value;
93*795d594fSAndroid Build Coastguard Worker       value.sival_ptr = nullptr;
94*795d594fSAndroid Build Coastguard Worker       sigqueue(getpid(), SIGSEGV, value);
95*795d594fSAndroid Build Coastguard Worker   }
96*795d594fSAndroid Build Coastguard Worker };
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker 
TestSignalBlocking(const std::function<void ()> & fn)99*795d594fSAndroid Build Coastguard Worker static void TestSignalBlocking(const std::function<void()>& fn) {
100*795d594fSAndroid Build Coastguard Worker   // Unblock SIGSEGV, make sure it stays unblocked.
101*795d594fSAndroid Build Coastguard Worker   sigset64_t mask;
102*795d594fSAndroid Build Coastguard Worker   sigemptyset64(&mask);
103*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(0, RealSigprocmask(SIG_SETMASK, &mask, nullptr)) << strerror(errno);
104*795d594fSAndroid Build Coastguard Worker 
105*795d594fSAndroid Build Coastguard Worker   fn();
106*795d594fSAndroid Build Coastguard Worker 
107*795d594fSAndroid Build Coastguard Worker   if (testing::Test::HasFatalFailure()) return;
108*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(0, RealSigprocmask(SIG_SETMASK, nullptr, &mask));
109*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(sigismember64(&mask, SIGSEGV));
110*795d594fSAndroid Build Coastguard Worker }
111*795d594fSAndroid Build Coastguard Worker 
TEST_F(SigchainTest,sigprocmask_setmask)112*795d594fSAndroid Build Coastguard Worker TEST_F(SigchainTest, sigprocmask_setmask) {
113*795d594fSAndroid Build Coastguard Worker   TestSignalBlocking([]() {
114*795d594fSAndroid Build Coastguard Worker     sigset_t mask;
115*795d594fSAndroid Build Coastguard Worker     sigfillset(&mask);
116*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &mask, nullptr));
117*795d594fSAndroid Build Coastguard Worker   });
118*795d594fSAndroid Build Coastguard Worker }
119*795d594fSAndroid Build Coastguard Worker 
TEST_F(SigchainTest,sigprocmask_block)120*795d594fSAndroid Build Coastguard Worker TEST_F(SigchainTest, sigprocmask_block) {
121*795d594fSAndroid Build Coastguard Worker   TestSignalBlocking([]() {
122*795d594fSAndroid Build Coastguard Worker     sigset_t mask;
123*795d594fSAndroid Build Coastguard Worker     sigfillset(&mask);
124*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &mask, nullptr));
125*795d594fSAndroid Build Coastguard Worker   });
126*795d594fSAndroid Build Coastguard Worker }
127*795d594fSAndroid Build Coastguard Worker 
128*795d594fSAndroid Build Coastguard Worker // bionic-only wide variants for LP32.
129*795d594fSAndroid Build Coastguard Worker #if defined(__BIONIC__)
TEST_F(SigchainTest,sigprocmask64_setmask)130*795d594fSAndroid Build Coastguard Worker TEST_F(SigchainTest, sigprocmask64_setmask) {
131*795d594fSAndroid Build Coastguard Worker   TestSignalBlocking([]() {
132*795d594fSAndroid Build Coastguard Worker     sigset64_t mask;
133*795d594fSAndroid Build Coastguard Worker     sigfillset64(&mask);
134*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(0, sigprocmask64(SIG_SETMASK, &mask, nullptr));
135*795d594fSAndroid Build Coastguard Worker   });
136*795d594fSAndroid Build Coastguard Worker }
137*795d594fSAndroid Build Coastguard Worker 
TEST_F(SigchainTest,sigprocmask64_block)138*795d594fSAndroid Build Coastguard Worker TEST_F(SigchainTest, sigprocmask64_block) {
139*795d594fSAndroid Build Coastguard Worker   TestSignalBlocking([]() {
140*795d594fSAndroid Build Coastguard Worker     sigset64_t mask;
141*795d594fSAndroid Build Coastguard Worker     sigfillset64(&mask);
142*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &mask, nullptr));
143*795d594fSAndroid Build Coastguard Worker   });
144*795d594fSAndroid Build Coastguard Worker }
145*795d594fSAndroid Build Coastguard Worker 
TEST_F(SigchainTest,pthread_sigmask64_setmask)146*795d594fSAndroid Build Coastguard Worker TEST_F(SigchainTest, pthread_sigmask64_setmask) {
147*795d594fSAndroid Build Coastguard Worker   TestSignalBlocking([]() {
148*795d594fSAndroid Build Coastguard Worker     sigset64_t mask;
149*795d594fSAndroid Build Coastguard Worker     sigfillset64(&mask);
150*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(0, pthread_sigmask64(SIG_SETMASK, &mask, nullptr));
151*795d594fSAndroid Build Coastguard Worker   });
152*795d594fSAndroid Build Coastguard Worker }
153*795d594fSAndroid Build Coastguard Worker 
TEST_F(SigchainTest,pthread_sigmask64_block)154*795d594fSAndroid Build Coastguard Worker TEST_F(SigchainTest, pthread_sigmask64_block) {
155*795d594fSAndroid Build Coastguard Worker   TestSignalBlocking([]() {
156*795d594fSAndroid Build Coastguard Worker     sigset64_t mask;
157*795d594fSAndroid Build Coastguard Worker     sigfillset64(&mask);
158*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, &mask, nullptr));
159*795d594fSAndroid Build Coastguard Worker   });
160*795d594fSAndroid Build Coastguard Worker }
161*795d594fSAndroid Build Coastguard Worker #endif
162*795d594fSAndroid Build Coastguard Worker 
163*795d594fSAndroid Build Coastguard Worker // glibc doesn't implement most of these in terms of sigprocmask, which we rely on.
164*795d594fSAndroid Build Coastguard Worker #if defined(__BIONIC__)
TEST_F(SigchainTest,pthread_sigmask_setmask)165*795d594fSAndroid Build Coastguard Worker TEST_F(SigchainTest, pthread_sigmask_setmask) {
166*795d594fSAndroid Build Coastguard Worker   TestSignalBlocking([]() {
167*795d594fSAndroid Build Coastguard Worker     sigset_t mask;
168*795d594fSAndroid Build Coastguard Worker     sigfillset(&mask);
169*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &mask, nullptr));
170*795d594fSAndroid Build Coastguard Worker   });
171*795d594fSAndroid Build Coastguard Worker }
172*795d594fSAndroid Build Coastguard Worker 
TEST_F(SigchainTest,pthread_sigmask_block)173*795d594fSAndroid Build Coastguard Worker TEST_F(SigchainTest, pthread_sigmask_block) {
174*795d594fSAndroid Build Coastguard Worker   TestSignalBlocking([]() {
175*795d594fSAndroid Build Coastguard Worker     sigset_t mask;
176*795d594fSAndroid Build Coastguard Worker     sigfillset(&mask);
177*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, &mask, nullptr));
178*795d594fSAndroid Build Coastguard Worker   });
179*795d594fSAndroid Build Coastguard Worker }
180*795d594fSAndroid Build Coastguard Worker 
TEST_F(SigchainTest,sigset_mask)181*795d594fSAndroid Build Coastguard Worker TEST_F(SigchainTest, sigset_mask) {
182*795d594fSAndroid Build Coastguard Worker   TestSignalBlocking([]() {
183*795d594fSAndroid Build Coastguard Worker     sigset(SIGSEGV, SIG_HOLD);
184*795d594fSAndroid Build Coastguard Worker   });
185*795d594fSAndroid Build Coastguard Worker }
186*795d594fSAndroid Build Coastguard Worker 
TEST_F(SigchainTest,sighold)187*795d594fSAndroid Build Coastguard Worker TEST_F(SigchainTest, sighold) {
188*795d594fSAndroid Build Coastguard Worker   TestSignalBlocking([]() {
189*795d594fSAndroid Build Coastguard Worker     sighold(SIGSEGV);
190*795d594fSAndroid Build Coastguard Worker   });
191*795d594fSAndroid Build Coastguard Worker }
192*795d594fSAndroid Build Coastguard Worker 
193*795d594fSAndroid Build Coastguard Worker #if !defined(__riscv)
194*795d594fSAndroid Build Coastguard Worker // Not exposed via headers, but the symbols are available if you declare them yourself.
195*795d594fSAndroid Build Coastguard Worker extern "C" int sigblock(int);
TEST_F(SigchainTest,sigblock)196*795d594fSAndroid Build Coastguard Worker TEST_F(SigchainTest, sigblock) {
197*795d594fSAndroid Build Coastguard Worker   TestSignalBlocking([]() {
198*795d594fSAndroid Build Coastguard Worker     int mask = ~0U;
199*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(0, sigblock(mask));
200*795d594fSAndroid Build Coastguard Worker   });
201*795d594fSAndroid Build Coastguard Worker }
202*795d594fSAndroid Build Coastguard Worker extern "C" int sigsetmask(int);
TEST_F(SigchainTest,sigsetmask)203*795d594fSAndroid Build Coastguard Worker TEST_F(SigchainTest, sigsetmask) {
204*795d594fSAndroid Build Coastguard Worker   TestSignalBlocking([]() {
205*795d594fSAndroid Build Coastguard Worker     int mask = ~0U;
206*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(0, sigsetmask(mask));
207*795d594fSAndroid Build Coastguard Worker   });
208*795d594fSAndroid Build Coastguard Worker }
209*795d594fSAndroid Build Coastguard Worker #endif
210*795d594fSAndroid Build Coastguard Worker 
211*795d594fSAndroid Build Coastguard Worker #endif
212*795d594fSAndroid Build Coastguard Worker 
213*795d594fSAndroid Build Coastguard Worker // Make sure that we properly put ourselves back in front if we get circumvented.
TEST_F(SigchainTest,EnsureFrontOfChain)214*795d594fSAndroid Build Coastguard Worker TEST_F(SigchainTest, EnsureFrontOfChain) {
215*795d594fSAndroid Build Coastguard Worker #if defined(__BIONIC__)
216*795d594fSAndroid Build Coastguard Worker   constexpr char kLibcSoName[] = "libc.so";
217*795d594fSAndroid Build Coastguard Worker #elif defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ == 6
218*795d594fSAndroid Build Coastguard Worker   constexpr char kLibcSoName[] = "libc.so.6";
219*795d594fSAndroid Build Coastguard Worker #elif defined(ANDROID_HOST_MUSL)
220*795d594fSAndroid Build Coastguard Worker   constexpr char kLibcSoName[] = "libc_musl.so";
221*795d594fSAndroid Build Coastguard Worker #else
222*795d594fSAndroid Build Coastguard Worker   #error Unknown libc
223*795d594fSAndroid Build Coastguard Worker #endif
224*795d594fSAndroid Build Coastguard Worker   void* libc = dlopen(kLibcSoName, RTLD_LAZY | RTLD_NOLOAD);
225*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(libc);
226*795d594fSAndroid Build Coastguard Worker 
227*795d594fSAndroid Build Coastguard Worker   auto libc_sigaction = reinterpret_cast<decltype(&sigaction)>(dlsym(libc, "sigaction"));
228*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(libc_sigaction);
229*795d594fSAndroid Build Coastguard Worker 
230*795d594fSAndroid Build Coastguard Worker   static sig_atomic_t called = 0;
231*795d594fSAndroid Build Coastguard Worker   struct sigaction action = {};
232*795d594fSAndroid Build Coastguard Worker   action.sa_flags = SA_SIGINFO;
233*795d594fSAndroid Build Coastguard Worker   action.sa_sigaction = [](int, siginfo_t*, void*) { called = 1; };
234*795d594fSAndroid Build Coastguard Worker 
235*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(0, libc_sigaction(SIGSEGV, &action, nullptr));
236*795d594fSAndroid Build Coastguard Worker 
237*795d594fSAndroid Build Coastguard Worker   // Try before EnsureFrontOfChain.
238*795d594fSAndroid Build Coastguard Worker   RaiseHandled();
239*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(1, called);
240*795d594fSAndroid Build Coastguard Worker   called = 0;
241*795d594fSAndroid Build Coastguard Worker 
242*795d594fSAndroid Build Coastguard Worker   RaiseUnhandled();
243*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(1, called);
244*795d594fSAndroid Build Coastguard Worker   called = 0;
245*795d594fSAndroid Build Coastguard Worker 
246*795d594fSAndroid Build Coastguard Worker   // ...and after.
247*795d594fSAndroid Build Coastguard Worker   art::EnsureFrontOfChain(SIGSEGV);
248*795d594fSAndroid Build Coastguard Worker   RaiseHandled();
249*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(0, called);
250*795d594fSAndroid Build Coastguard Worker 
251*795d594fSAndroid Build Coastguard Worker   RaiseUnhandled();
252*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(1, called);
253*795d594fSAndroid Build Coastguard Worker   called = 0;
254*795d594fSAndroid Build Coastguard Worker }
255*795d594fSAndroid Build Coastguard Worker 
256*795d594fSAndroid Build Coastguard Worker #if defined(__aarch64__)
257*795d594fSAndroid Build Coastguard Worker // The test intentionally dereferences (tagged) null to trigger SIGSEGV.
258*795d594fSAndroid Build Coastguard Worker // We need to disable HWASAN since it would catch the dereference first.
fault_address_tag_impl()259*795d594fSAndroid Build Coastguard Worker DISABLE_HWASAN void fault_address_tag_impl() {
260*795d594fSAndroid Build Coastguard Worker   struct sigaction action = {};
261*795d594fSAndroid Build Coastguard Worker   action.sa_flags = SA_SIGINFO;
262*795d594fSAndroid Build Coastguard Worker   action.sa_sigaction = [](int, siginfo_t* siginfo, void*) {
263*795d594fSAndroid Build Coastguard Worker     _exit(reinterpret_cast<uintptr_t>(siginfo->si_addr) >> 56);
264*795d594fSAndroid Build Coastguard Worker   };
265*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(0, sigaction(SIGSEGV, &action, nullptr));
266*795d594fSAndroid Build Coastguard Worker 
267*795d594fSAndroid Build Coastguard Worker   auto* tagged_null = reinterpret_cast<int*>(0x2bULL << 56);
268*795d594fSAndroid Build Coastguard Worker   EXPECT_EXIT(
269*795d594fSAndroid Build Coastguard Worker       { [[maybe_unused]] volatile int load = *tagged_null; }, testing::ExitedWithCode(0), "");
270*795d594fSAndroid Build Coastguard Worker 
271*795d594fSAndroid Build Coastguard Worker   // Our sigaction implementation always implements the "clear unknown bits"
272*795d594fSAndroid Build Coastguard Worker   // semantics for oldact.sa_flags regardless of kernel version so we rely on it
273*795d594fSAndroid Build Coastguard Worker   // here to test for kernel support for SA_EXPOSE_TAGBITS.
274*795d594fSAndroid Build Coastguard Worker   action.sa_flags = SA_SIGINFO | SA_EXPOSE_TAGBITS;
275*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(0, sigaction(SIGSEGV, &action, nullptr));
276*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(0, sigaction(SIGSEGV, nullptr, &action));
277*795d594fSAndroid Build Coastguard Worker   if (action.sa_flags & SA_EXPOSE_TAGBITS) {
278*795d594fSAndroid Build Coastguard Worker       EXPECT_EXIT({ [[maybe_unused]] volatile int load = *tagged_null; },
279*795d594fSAndroid Build Coastguard Worker                   testing::ExitedWithCode(0x2b),
280*795d594fSAndroid Build Coastguard Worker                   "");
281*795d594fSAndroid Build Coastguard Worker   }
282*795d594fSAndroid Build Coastguard Worker }
283*795d594fSAndroid Build Coastguard Worker #endif
284*795d594fSAndroid Build Coastguard Worker 
TEST_F(SigchainTest,fault_address_tag)285*795d594fSAndroid Build Coastguard Worker TEST_F(SigchainTest, fault_address_tag) {
286*795d594fSAndroid Build Coastguard Worker #define SA_EXPOSE_TAGBITS 0x00000800
287*795d594fSAndroid Build Coastguard Worker #if defined(__aarch64__)
288*795d594fSAndroid Build Coastguard Worker   fault_address_tag_impl();
289*795d594fSAndroid Build Coastguard Worker #else
290*795d594fSAndroid Build Coastguard Worker   GTEST_SKIP() << "arm64 only";
291*795d594fSAndroid Build Coastguard Worker #endif
292*795d594fSAndroid Build Coastguard Worker }
293