1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <jni.h>
20*795d594fSAndroid Build Coastguard Worker #include <signal.h>
21*795d594fSAndroid Build Coastguard Worker #include <stdio.h>
22*795d594fSAndroid Build Coastguard Worker #include <stdlib.h>
23*795d594fSAndroid Build Coastguard Worker #include <string.h>
24*795d594fSAndroid Build Coastguard Worker #include <sys/ucontext.h>
25*795d594fSAndroid Build Coastguard Worker #include <unistd.h>
26*795d594fSAndroid Build Coastguard Worker
27*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
28*795d594fSAndroid Build Coastguard Worker
29*795d594fSAndroid Build Coastguard Worker static int signal_count;
30*795d594fSAndroid Build Coastguard Worker static const int kMaxSignal = 1;
31*795d594fSAndroid Build Coastguard Worker
32*795d594fSAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
33*795d594fSAndroid Build Coastguard Worker #if defined(__APPLE__)
34*795d594fSAndroid Build Coastguard Worker #define ucontext __darwin_ucontext
35*795d594fSAndroid Build Coastguard Worker
36*795d594fSAndroid Build Coastguard Worker #if defined(__x86_64__)
37*795d594fSAndroid Build Coastguard Worker // 64 bit mac build.
38*795d594fSAndroid Build Coastguard Worker #define CTX_EIP uc_mcontext->__ss.__rip
39*795d594fSAndroid Build Coastguard Worker #else
40*795d594fSAndroid Build Coastguard Worker // 32 bit mac build.
41*795d594fSAndroid Build Coastguard Worker #define CTX_EIP uc_mcontext->__ss.__eip
42*795d594fSAndroid Build Coastguard Worker #endif
43*795d594fSAndroid Build Coastguard Worker
44*795d594fSAndroid Build Coastguard Worker #elif defined(__x86_64__)
45*795d594fSAndroid Build Coastguard Worker // 64 bit linux build.
46*795d594fSAndroid Build Coastguard Worker #define CTX_EIP uc_mcontext.gregs[REG_RIP]
47*795d594fSAndroid Build Coastguard Worker #else
48*795d594fSAndroid Build Coastguard Worker // 32 bit linux build.
49*795d594fSAndroid Build Coastguard Worker #define CTX_EIP uc_mcontext.gregs[REG_EIP]
50*795d594fSAndroid Build Coastguard Worker #endif
51*795d594fSAndroid Build Coastguard Worker #endif
52*795d594fSAndroid Build Coastguard Worker
53*795d594fSAndroid Build Coastguard Worker #define BLOCKED_SIGNAL SIGUSR1
54*795d594fSAndroid Build Coastguard Worker #define UNBLOCKED_SIGNAL SIGUSR2
55*795d594fSAndroid Build Coastguard Worker
blocked_signal(int sig)56*795d594fSAndroid Build Coastguard Worker static void blocked_signal([[maybe_unused]] int sig) {
57*795d594fSAndroid Build Coastguard Worker printf("blocked signal received\n");
58*795d594fSAndroid Build Coastguard Worker }
59*795d594fSAndroid Build Coastguard Worker
unblocked_signal(int sig)60*795d594fSAndroid Build Coastguard Worker static void unblocked_signal([[maybe_unused]] int sig) {
61*795d594fSAndroid Build Coastguard Worker printf("unblocked signal received\n");
62*795d594fSAndroid Build Coastguard Worker }
63*795d594fSAndroid Build Coastguard Worker
signalhandler(int sig,siginfo_t * info,void * context)64*795d594fSAndroid Build Coastguard Worker static void signalhandler([[maybe_unused]] int sig, [[maybe_unused]] siginfo_t* info,
65*795d594fSAndroid Build Coastguard Worker void* context) {
66*795d594fSAndroid Build Coastguard Worker printf("signal caught\n");
67*795d594fSAndroid Build Coastguard Worker ++signal_count;
68*795d594fSAndroid Build Coastguard Worker if (signal_count > kMaxSignal) {
69*795d594fSAndroid Build Coastguard Worker abort();
70*795d594fSAndroid Build Coastguard Worker }
71*795d594fSAndroid Build Coastguard Worker
72*795d594fSAndroid Build Coastguard Worker raise(UNBLOCKED_SIGNAL);
73*795d594fSAndroid Build Coastguard Worker raise(BLOCKED_SIGNAL);
74*795d594fSAndroid Build Coastguard Worker printf("unblocking blocked signal\n");
75*795d594fSAndroid Build Coastguard Worker
76*795d594fSAndroid Build Coastguard Worker sigset_t mask;
77*795d594fSAndroid Build Coastguard Worker sigemptyset(&mask);
78*795d594fSAndroid Build Coastguard Worker sigaddset(&mask, BLOCKED_SIGNAL);
79*795d594fSAndroid Build Coastguard Worker sigprocmask(SIG_UNBLOCK, &mask, nullptr);
80*795d594fSAndroid Build Coastguard Worker
81*795d594fSAndroid Build Coastguard Worker #if defined(__arm__)
82*795d594fSAndroid Build Coastguard Worker ucontext_t* uc = reinterpret_cast<ucontext_t*>(context);
83*795d594fSAndroid Build Coastguard Worker mcontext_t* mc = reinterpret_cast<mcontext_t*>(&uc->uc_mcontext);
84*795d594fSAndroid Build Coastguard Worker mc->arm_pc += 2; // Skip instruction causing segv.
85*795d594fSAndroid Build Coastguard Worker #elif defined(__aarch64__)
86*795d594fSAndroid Build Coastguard Worker ucontext_t* uc = reinterpret_cast<ucontext_t*>(context);
87*795d594fSAndroid Build Coastguard Worker mcontext_t* mc = reinterpret_cast<mcontext_t*>(&uc->uc_mcontext);
88*795d594fSAndroid Build Coastguard Worker mc->pc += 4; // Skip instruction causing segv.
89*795d594fSAndroid Build Coastguard Worker #elif defined(__riscv)
90*795d594fSAndroid Build Coastguard Worker ucontext_t* uc = reinterpret_cast<ucontext_t*>(context);
91*795d594fSAndroid Build Coastguard Worker mcontext_t* mc = reinterpret_cast<mcontext_t*>(&uc->uc_mcontext);
92*795d594fSAndroid Build Coastguard Worker mc->__gregs[REG_PC] += 4; // Skip instruction causing segv.
93*795d594fSAndroid Build Coastguard Worker #elif defined(__i386__)
94*795d594fSAndroid Build Coastguard Worker ucontext_t* uc = reinterpret_cast<ucontext_t*>(context);
95*795d594fSAndroid Build Coastguard Worker uc->CTX_EIP += 3;
96*795d594fSAndroid Build Coastguard Worker #elif defined(__x86_64__)
97*795d594fSAndroid Build Coastguard Worker ucontext_t* uc = reinterpret_cast<ucontext_t*>(context);
98*795d594fSAndroid Build Coastguard Worker uc->CTX_EIP += 2;
99*795d594fSAndroid Build Coastguard Worker #else
100*795d594fSAndroid Build Coastguard Worker UNUSED(context);
101*795d594fSAndroid Build Coastguard Worker UNIMPLEMENTED(FATAL) << "Unsupported architecture";
102*795d594fSAndroid Build Coastguard Worker #endif
103*795d594fSAndroid Build Coastguard Worker
104*795d594fSAndroid Build Coastguard Worker printf("signal handler done\n");
105*795d594fSAndroid Build Coastguard Worker }
106*795d594fSAndroid Build Coastguard Worker
107*795d594fSAndroid Build Coastguard Worker static struct sigaction oldaction;
108*795d594fSAndroid Build Coastguard Worker
compare_sigaction(const struct sigaction * lhs,const struct sigaction * rhs)109*795d594fSAndroid Build Coastguard Worker bool compare_sigaction(const struct sigaction* lhs, const struct sigaction* rhs) {
110*795d594fSAndroid Build Coastguard Worker // bionic's definition of `struct sigaction` has internal padding bytes, so we can't just do a
111*795d594fSAndroid Build Coastguard Worker // naive memcmp of the entire struct.
112*795d594fSAndroid Build Coastguard Worker #if defined(SA_RESTORER)
113*795d594fSAndroid Build Coastguard Worker if (lhs->sa_restorer != rhs->sa_restorer) {
114*795d594fSAndroid Build Coastguard Worker return false;
115*795d594fSAndroid Build Coastguard Worker }
116*795d594fSAndroid Build Coastguard Worker #endif
117*795d594fSAndroid Build Coastguard Worker return memcmp(&lhs->sa_mask, &rhs->sa_mask, sizeof(lhs->sa_mask)) == 0 &&
118*795d594fSAndroid Build Coastguard Worker lhs->sa_sigaction == rhs->sa_sigaction &&
119*795d594fSAndroid Build Coastguard Worker lhs->sa_flags == rhs->sa_flags;
120*795d594fSAndroid Build Coastguard Worker }
121*795d594fSAndroid Build Coastguard Worker
Java_Main_initSignalTest(JNIEnv *,jclass)122*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT void JNICALL Java_Main_initSignalTest(JNIEnv*, jclass) {
123*795d594fSAndroid Build Coastguard Worker struct sigaction action;
124*795d594fSAndroid Build Coastguard Worker action.sa_sigaction = signalhandler;
125*795d594fSAndroid Build Coastguard Worker sigfillset(&action.sa_mask);
126*795d594fSAndroid Build Coastguard Worker sigdelset(&action.sa_mask, UNBLOCKED_SIGNAL);
127*795d594fSAndroid Build Coastguard Worker action.sa_flags = SA_SIGINFO | SA_ONSTACK;
128*795d594fSAndroid Build Coastguard Worker #if !defined(__APPLE__)
129*795d594fSAndroid Build Coastguard Worker action.sa_restorer = nullptr;
130*795d594fSAndroid Build Coastguard Worker #endif
131*795d594fSAndroid Build Coastguard Worker
132*795d594fSAndroid Build Coastguard Worker sigaction(SIGSEGV, &action, &oldaction);
133*795d594fSAndroid Build Coastguard Worker struct sigaction check;
134*795d594fSAndroid Build Coastguard Worker sigaction(SIGSEGV, nullptr, &check);
135*795d594fSAndroid Build Coastguard Worker if (!compare_sigaction(&check, &action)) {
136*795d594fSAndroid Build Coastguard Worker printf("sigaction returned different value\n");
137*795d594fSAndroid Build Coastguard Worker printf("action.sa_mask = %p, check.sa_mask = %p\n",
138*795d594fSAndroid Build Coastguard Worker *reinterpret_cast<void**>(&action.sa_mask),
139*795d594fSAndroid Build Coastguard Worker *reinterpret_cast<void**>(&check.sa_mask));
140*795d594fSAndroid Build Coastguard Worker printf("action.sa_sigaction = %p, check.sa_sigaction = %p\n",
141*795d594fSAndroid Build Coastguard Worker action.sa_sigaction, check.sa_sigaction);
142*795d594fSAndroid Build Coastguard Worker printf("action.sa_flags = %x, check.sa_flags = %x\n",
143*795d594fSAndroid Build Coastguard Worker action.sa_flags, check.sa_flags);
144*795d594fSAndroid Build Coastguard Worker }
145*795d594fSAndroid Build Coastguard Worker signal(BLOCKED_SIGNAL, blocked_signal);
146*795d594fSAndroid Build Coastguard Worker signal(UNBLOCKED_SIGNAL, unblocked_signal);
147*795d594fSAndroid Build Coastguard Worker }
148*795d594fSAndroid Build Coastguard Worker
Java_Main_terminateSignalTest(JNIEnv *,jclass)149*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT void JNICALL Java_Main_terminateSignalTest(JNIEnv*, jclass) {
150*795d594fSAndroid Build Coastguard Worker sigaction(SIGSEGV, &oldaction, nullptr);
151*795d594fSAndroid Build Coastguard Worker }
152*795d594fSAndroid Build Coastguard Worker
153*795d594fSAndroid Build Coastguard Worker // Prevent the compiler being a smart-alec and optimizing out the assignment
154*795d594fSAndroid Build Coastguard Worker // to null.
155*795d594fSAndroid Build Coastguard Worker char *go_away_compiler = nullptr;
156*795d594fSAndroid Build Coastguard Worker
Java_Main_testSignal(JNIEnv *,jclass)157*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jint JNICALL Java_Main_testSignal(JNIEnv*, jclass) {
158*795d594fSAndroid Build Coastguard Worker // Unblock UNBLOCKED_SIGNAL.
159*795d594fSAndroid Build Coastguard Worker sigset_t mask;
160*795d594fSAndroid Build Coastguard Worker memset(&mask, 0, sizeof(mask));
161*795d594fSAndroid Build Coastguard Worker sigaddset(&mask, UNBLOCKED_SIGNAL);
162*795d594fSAndroid Build Coastguard Worker sigprocmask(SIG_UNBLOCK, &mask, nullptr);
163*795d594fSAndroid Build Coastguard Worker
164*795d594fSAndroid Build Coastguard Worker #if defined(__arm__) || defined(__i386__) || defined(__aarch64__)
165*795d594fSAndroid Build Coastguard Worker // On supported architectures we cause a real SEGV.
166*795d594fSAndroid Build Coastguard Worker *go_away_compiler = 'a';
167*795d594fSAndroid Build Coastguard Worker #elif defined(__riscv)
168*795d594fSAndroid Build Coastguard Worker // Cause a SEGV using an instruction known to be 4 bytes long to account for hardcoded jump
169*795d594fSAndroid Build Coastguard Worker // in the signal handler
170*795d594fSAndroid Build Coastguard Worker asm volatile("ld zero, (zero);" : : :);
171*795d594fSAndroid Build Coastguard Worker #elif defined(__x86_64__)
172*795d594fSAndroid Build Coastguard Worker // Cause a SEGV using an instruction known to be 2 bytes long to account for hardcoded jump
173*795d594fSAndroid Build Coastguard Worker // in the signal handler
174*795d594fSAndroid Build Coastguard Worker asm volatile("movl $0, %%eax;" "movb %%ah, (%%rax);" : : : "%eax");
175*795d594fSAndroid Build Coastguard Worker #else
176*795d594fSAndroid Build Coastguard Worker // On other architectures we simulate SEGV.
177*795d594fSAndroid Build Coastguard Worker kill(getpid(), SIGSEGV);
178*795d594fSAndroid Build Coastguard Worker #endif
179*795d594fSAndroid Build Coastguard Worker return 1234;
180*795d594fSAndroid Build Coastguard Worker }
181