1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "gtest/gtest.h"
18 
19 #include <errno.h>
20 #include <pthread.h>
21 #include <semaphore.h>
22 #include <setjmp.h>
23 #include <signal.h>
24 #include <sys/mman.h>
25 #include <sys/syscall.h>
26 #include <sys/time.h>
27 
28 #include <atomic>
29 
30 #include "berberis/ndk_program_tests/scoped_sigaction.h"
31 
32 namespace {
33 
EnsureSignalsChecked()34 void EnsureSignalsChecked() {
35   // Emulated signals should be checked on return from wrapped syscall.
36   // Real signals should be checked on exit from kernel mode.
37   syscall(SYS_gettid);
38 }
39 
HandleSignal(int)40 void HandleSignal(int) {
41   return;
42 }
43 
TEST(Signal,SigkillSigactionFails)44 TEST(Signal, SigkillSigactionFails) {
45   struct sigaction sa {};
46   sa.sa_handler = HandleSignal;
47   ASSERT_EQ(sigaction(SIGKILL, &sa, nullptr), -1);
48 }
49 
50 struct ThreadParam {
51   pthread_t self;
52   int id;
53   std::atomic_bool started;
54   std::atomic_bool stop;
55 };
56 
57 const int kMaxThreads = 20;
58 ThreadParam g_params[kMaxThreads];
59 
AreAllThreadsStarted()60 bool AreAllThreadsStarted() {
61   for (int i = 0; i < kMaxThreads; i++) {
62     if (!g_params[i].started) {
63       return false;
64     }
65   }
66   return true;
67 }
68 
AreAllThreadsStopped()69 bool AreAllThreadsStopped() {
70   for (int i = 0; i < kMaxThreads; i++) {
71     if (!g_params[i].stop) {
72       return false;
73     }
74   }
75   return true;
76 }
77 
ThreadSignalHandler(int,siginfo_t *,void *)78 void ThreadSignalHandler(int /* sig */, siginfo_t* /* info */, void* /* ctx */) {
79   pthread_t me = pthread_self();
80   for (int i = 0; i < kMaxThreads; i++) {
81     if (g_params[i].self == me) {
82       g_params[i].stop = true;
83       return;
84     }
85   }
86 }
87 
ThreadRunner(void * arg)88 void* ThreadRunner(void* arg) {
89   ThreadParam* param = reinterpret_cast<ThreadParam*>(arg);
90   fprintf(stderr, "Thread %d started\n", param->id);
91   param->started = true;
92   while (!param->stop) {
93     sched_yield();
94   }
95   fprintf(stderr, "Thread %d exited\n", param->id);
96   return nullptr;
97 }
98 
TEST(Signal,PthreadKillTest)99 TEST(Signal, PthreadKillTest) {
100   const int sig_num = SIGPWR;
101 
102   struct sigaction sa;
103   sa.sa_flags = SA_SIGINFO;
104   sigemptyset(&sa.sa_mask);
105   sa.sa_sigaction = ThreadSignalHandler;
106   ScopedSigaction scoped_sa(sig_num, &sa);
107 
108   // Initialize globals here to allow test repetition.
109   for (int i = 0; i < kMaxThreads; i++) {
110     g_params[i].id = i;
111     g_params[i].started = false;
112     g_params[i].stop = false;
113   }
114 
115   for (int i = 0; i < kMaxThreads; i++) {
116     int rv = pthread_create(&g_params[i].self, nullptr, ThreadRunner, &g_params[i]);
117     ASSERT_EQ(rv, 0);
118   }
119   fprintf(stderr, "All threads created\n");
120 
121   while (!AreAllThreadsStarted()) {
122     sched_yield();
123   }
124   fprintf(stderr, "All threads started\n");
125 
126   // Send them a signal.
127   for (int i = 0; i < kMaxThreads; i++) {
128     int rv = pthread_kill(g_params[i].self, sig_num);
129     ASSERT_EQ(rv, 0);
130   }
131   fprintf(stderr, "All threads killed\n");
132 
133   while (!AreAllThreadsStopped()) {
134     sched_yield();
135   }
136   fprintf(stderr, "All threads stopped\n");
137 
138   for (int i = 0; i < kMaxThreads; i++) {
139     int rv = pthread_join(g_params[i].self, nullptr);
140     ASSERT_EQ(rv, 0);
141   }
142   fprintf(stderr, "All threads exited\n");
143 }
144 
145 int* g_data_page;
146 
SigsegvSignalHandler(int,siginfo_t * info,void *)147 void SigsegvSignalHandler(int /* sig */, siginfo_t* info, void* /* ctx */) {
148   fprintf(stderr, "SIGSEGV caught\n");
149   EXPECT_TRUE(SI_FROMKERNEL(info));
150   mprotect(g_data_page, 4096, PROT_WRITE);
151 }
152 
TEST(Signal,Sigsegv)153 TEST(Signal, Sigsegv) {
154   g_data_page = static_cast<int*>(mmap(0, 4096, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
155 
156   struct sigaction sa;
157   sa.sa_flags = SA_SIGINFO;
158   sigemptyset(&sa.sa_mask);
159   sa.sa_sigaction = SigsegvSignalHandler;
160   ScopedSigaction scoped_sa(SIGSEGV, &sa);
161 
162   g_data_page[5] = 0;
163 
164   munmap(g_data_page, 4096);
165 }
166 
167 bool g_async_sigsegv_received = false;
168 
AsyncSigsegvSignalHandler(int,siginfo_t * info,void *)169 void AsyncSigsegvSignalHandler(int /* sig */, siginfo_t* info, void* /* ctx */) {
170   fprintf(stderr, "Async SIGSEGV caught\n");
171   // si_pid must be set for signals sent by kill.
172   EXPECT_EQ(getpid(), info->si_pid);
173   EXPECT_TRUE(SI_FROMUSER(info));
174   g_async_sigsegv_received = true;
175 }
176 
AsyncSigsegvSender(void * arg)177 void* AsyncSigsegvSender(void* arg) {
178   pthread_t* parent_id = static_cast<pthread_t*>(arg);
179   EXPECT_EQ(pthread_kill(*parent_id, SIGSEGV), 0);
180   return nullptr;
181 }
182 
TEST(Signal,AsyncSigsegv)183 TEST(Signal, AsyncSigsegv) {
184   struct sigaction sa {};
185   sa.sa_flags = SA_SIGINFO;
186   sa.sa_sigaction = AsyncSigsegvSignalHandler;
187   ScopedSigaction scoped_sa(SIGSEGV, &sa);
188 
189   g_async_sigsegv_received = false;
190   pthread_t parent_id = pthread_self();
191   pthread_t child_id;
192   ASSERT_EQ(pthread_create(&child_id, nullptr, AsyncSigsegvSender, &parent_id), 0);
193   ASSERT_EQ(pthread_join(child_id, nullptr), 0);
194   EnsureSignalsChecked();
195   ASSERT_TRUE(g_async_sigsegv_received);
196 }
197 
198 // Must be valid instruction address. 0 is invalid as the compiler optimizes call(0) to UD.
199 constexpr uintptr_t kNoExecAddr = 4096;
200 
201 sigjmp_buf g_recover_no_exec;
202 
NoExecSignalHandler(int,siginfo_t * info,void *)203 void NoExecSignalHandler(int /* sig */, siginfo_t* info, void* /* ctx */) {
204   uintptr_t addr = reinterpret_cast<uintptr_t>(info->si_addr);
205   EXPECT_EQ(addr, kNoExecAddr);
206   longjmp(g_recover_no_exec, 1);
207 }
208 
TEST(Signal,RecoverFromNoExec)209 TEST(Signal, RecoverFromNoExec) {
210   struct sigaction sa;
211   sa.sa_flags = SA_SIGINFO;
212   sigemptyset(&sa.sa_mask);
213   sa.sa_sigaction = NoExecSignalHandler;
214   ScopedSigaction scoped_sa(SIGSEGV, &sa);
215 
216   if (setjmp(g_recover_no_exec) == 0) {
217     using Func = void (*)();
218     (reinterpret_cast<Func>(kNoExecAddr))();
219     // Signal handler should longjmp out!
220     FAIL();
221   }
222 }
223 
224 int g_expected_signal;
225 bool g_is_received;
226 
CheckExpectedSignalHandler(int signal)227 void CheckExpectedSignalHandler(int signal) {
228   ASSERT_EQ(signal, g_expected_signal);
229   g_is_received = true;
230 }
231 
TEST(Signal,SigMask)232 TEST(Signal, SigMask) {
233   struct sigaction sa;
234   memset(&sa, 0, sizeof(sa));
235   sigemptyset(&sa.sa_mask);
236   sa.sa_handler = CheckExpectedSignalHandler;
237 
238   // Walk signals customizable by apps. Avoid signals handled by ART.
239   const int test_signals[] = {SIGILL, SIGXCPU, SIGPWR};
240 
241   for (size_t i = 0; i < sizeof(test_signals) / sizeof(test_signals[0]); ++i) {
242     int signal = test_signals[i];
243     ScopedSigaction scoped_sa(signal, &sa);
244 
245     sigset_t mask;
246 
247     // Block signal.
248     ASSERT_EQ(sigemptyset(&mask), 0);
249     ASSERT_EQ(sigaddset(&mask, signal), 0);
250     ASSERT_EQ(pthread_sigmask(SIG_BLOCK, &mask, nullptr), 0);
251 
252     // Send signal to itself. Expect it not to be delivered.
253     // NOTE: sending SIGILL with pthread_kill when blocked is well-defined!
254     g_expected_signal = -1;
255     g_is_received = false;
256     // raise() is not supported.
257     ASSERT_EQ(pthread_kill(pthread_self(), signal), 0);
258 
259     // This shouldn't trigger delivering of blocked signal.
260     EnsureSignalsChecked();
261 
262     // Unblock signal and expect it to be delivered.
263     g_expected_signal = signal;
264     ASSERT_EQ(sigemptyset(&mask), 0);
265     ASSERT_EQ(pthread_sigmask(SIG_SETMASK, &mask, nullptr), 0);
266 
267     // Wait until we receive it.
268     while (!g_is_received) {
269       sched_yield();
270     }
271   }
272 }
273 
274 std::atomic_bool g_started;
275 std::atomic_bool g_suspend_sent;
276 std::atomic_bool g_resume_sent;
277 std::atomic_bool g_suspend_handler_visited;
278 std::atomic_bool g_resume_handler_visited;
279 int g_expected_resume_signal;
280 
ResumeHandler(int signal)281 void ResumeHandler(int signal) {
282   ASSERT_EQ(signal, g_expected_resume_signal);
283   g_resume_handler_visited = true;
284 }
285 
SuspendHandler(int signal)286 void SuspendHandler(int signal) {
287   ASSERT_EQ(signal, SIGPWR);
288   g_suspend_handler_visited = true;
289 
290   // Check resume signal is blocked.
291   sigset_t current_mask;
292   pthread_sigmask(SIG_BLOCK, nullptr, &current_mask);
293   ASSERT_EQ(sigismember(&current_mask, SIGXCPU), 1);
294 
295   while (!g_resume_sent) {
296     sched_yield();
297   }
298   // Resume is sent, but should still be blocked.
299   EnsureSignalsChecked();
300 
301   // Now catch signal in sigsuspend with empty mask.
302   g_expected_resume_signal = SIGXCPU;
303   sigset_t suspend_mask;
304   sigemptyset(&suspend_mask);
305   sigsuspend(&suspend_mask);
306 
307   // Mask should be restored.
308   pthread_sigmask(SIG_BLOCK, nullptr, &current_mask);
309   ASSERT_EQ(sigismember(&current_mask, SIGXCPU), 1);
310 }
311 
WaitForSuspendRunner(void *)312 void* WaitForSuspendRunner(void* /* arg */) {
313   g_started = true;
314   while (!g_suspend_sent) {
315     sched_yield();
316   }
317   EnsureSignalsChecked();
318   return nullptr;
319 }
320 
TEST(Signal,SigActionAndSuspendMasks)321 TEST(Signal, SigActionAndSuspendMasks) {
322   // Set resume sigaction.
323   struct sigaction sa;
324   memset(&sa, 0, sizeof(sa));
325   sigemptyset(&sa.sa_mask);
326   sa.sa_handler = ResumeHandler;
327   ScopedSigaction scoped_xcpu(SIGXCPU, &sa);
328 
329   // Set suspend sigaction to block SIGXCPU in handler.
330   sigaddset(&sa.sa_mask, SIGXCPU);
331   sa.sa_handler = SuspendHandler;
332   ScopedSigaction scoped_pwr(SIGPWR, &sa);
333 
334   g_started = false;
335   g_suspend_sent = false;
336   g_resume_sent = false;
337   g_suspend_handler_visited = false;
338   g_resume_handler_visited = false;
339   g_expected_resume_signal = -1;
340 
341   // Start the second thread.
342   pthread_t child_id;
343   ASSERT_EQ(pthread_create(&child_id, nullptr, WaitForSuspendRunner, nullptr), 0);
344   while (!g_started) {
345     sched_yield();
346   }
347 
348   // Direct it into suspend handler and wait while it gets there.
349   ASSERT_EQ(pthread_kill(child_id, SIGPWR), 0);
350   g_suspend_sent = true;
351   while (!g_suspend_handler_visited) {
352     sched_yield();
353   }
354 
355   // Direct it further into resume handler and wait while it gets there.
356   ASSERT_EQ(pthread_kill(child_id, SIGXCPU), 0);
357   g_resume_sent = true;
358   while (!g_resume_handler_visited) {
359     sched_yield();
360   }
361 }
362 
363 volatile int g_handler_counter;
364 
SigActionDeferHandler(int signal)365 void SigActionDeferHandler(int signal) {
366   ASSERT_EQ(signal, SIGPWR);
367 
368   static volatile bool in_handler = false;
369   ASSERT_FALSE(in_handler);
370   in_handler = true;
371 
372   if (g_handler_counter++ == 0) {
373     ASSERT_EQ(pthread_kill(pthread_self(), SIGPWR), 0);
374     EnsureSignalsChecked();
375   }
376 
377   in_handler = false;
378 }
379 
TEST(Signal,SigActionDefer)380 TEST(Signal, SigActionDefer) {
381   // Set resume sigaction.
382   struct sigaction sa;
383   memset(&sa, 0, sizeof(sa));
384 
385   g_handler_counter = 0;
386 
387   // When SA_NODEFER is unset, signal in blocked in its handler.
388   ASSERT_EQ(sigemptyset(&sa.sa_mask), 0);
389   sa.sa_handler = SigActionDeferHandler;
390   ScopedSigaction scoped_sa(SIGPWR, &sa);
391 
392   ASSERT_EQ(pthread_kill(pthread_self(), SIGPWR), 0);
393   // Should catch two signals: one from here and one from handler.
394   EnsureSignalsChecked();
395   EnsureSignalsChecked();
396   ASSERT_EQ(g_handler_counter, 2);
397 }
398 
SigActionNoDeferHandler(int signal)399 void SigActionNoDeferHandler(int signal) {
400   ASSERT_EQ(signal, SIGPWR);
401 
402   static volatile bool in_handler = false;
403   ASSERT_EQ(in_handler, (g_handler_counter == 1));
404   in_handler = true;
405 
406   if (g_handler_counter++ == 0) {
407     ASSERT_EQ(pthread_kill(pthread_self(), SIGPWR), 0);
408     EnsureSignalsChecked();
409   }
410 
411   // We set is to false while returning from the second handler
412   // to the first one. But it is ok, since we don't use it in
413   // the first handler anymore.
414   in_handler = false;
415 }
416 
TEST(Signal,SigActionNoDefer)417 TEST(Signal, SigActionNoDefer) {
418   // Set resume sigaction.
419   struct sigaction sa;
420   memset(&sa, 0, sizeof(sa));
421 
422   g_handler_counter = 0;
423 
424   // Now set sigaction with SA_NODEFER.
425   sa.sa_handler = SigActionNoDeferHandler;
426   sa.sa_flags |= SA_NODEFER;
427   ScopedSigaction scoped_sa(SIGPWR, &sa);
428 
429   ASSERT_EQ(pthread_kill(pthread_self(), SIGPWR), 0);
430   EnsureSignalsChecked();
431   ASSERT_EQ(g_handler_counter, 2);
432 }
433 
434 sem_t g_kill_and_wait_sem;
435 
KillAndSemWaitHandler(int signal)436 void KillAndSemWaitHandler(int signal) {
437   ASSERT_EQ(signal, SIGPWR);
438   // Notify parent that child is in handler.
439   ASSERT_EQ(sem_post(&g_kill_and_wait_sem), 0);
440 }
441 
KillAndSemWaitRunner(void *)442 void KillAndSemWaitRunner(void* /* arg */) {
443   // Register handler
444   struct sigaction sa;
445   memset(&sa, 0, sizeof(sa));
446   ASSERT_EQ(sigemptyset(&sa.sa_mask), 0);
447   sa.sa_handler = KillAndSemWaitHandler;
448   ScopedSigaction scoped_sa(SIGPWR, &sa);
449 
450   // Notify parent that child is ready to receive signals.
451   ASSERT_EQ(sem_post(&g_kill_and_wait_sem), 0);
452 
453   sigset_t suspend_mask;
454   ASSERT_EQ(sigemptyset(&suspend_mask), 0);
455 
456   // Ensure receiving some signals before exiting.
457   // Warning: we receive signals even outside sigsuspend!
458   for (int i = 0; i < 10; ++i) {
459     ASSERT_EQ(sigsuspend(&suspend_mask), -1);
460     ASSERT_EQ(errno, EINTR);
461   }
462 }
463 
KillAndSemWaitRunnerWrapper(void * arg)464 void* KillAndSemWaitRunnerWrapper(void* arg) {
465   // Assertions cannot be used in a function that returns non-void.
466   KillAndSemWaitRunner(arg);
467   return nullptr;
468 }
469 
470 // TODO(b/28014551): this test might be wrong, it seems even when pthread_kill returns 0 there is no
471 // guarantee that signal handler will be executed. For example, signal might be blocked until thread
472 // exit. Or, thread might be killed before starting the signal handler. Also, it is not clear what
473 // happens if signal arrives right when thread is going to finish.
474 // Investigate more if this test is valid or not!
TEST(Signal,DISABLED_SignalKillAndSemWaitTest)475 TEST(Signal, DISABLED_SignalKillAndSemWaitTest) {
476   sem_init(&g_kill_and_wait_sem, 0, 0);
477 
478   // Start thread.
479   pthread_t child_id;
480   ASSERT_EQ(pthread_create(&child_id, nullptr, KillAndSemWaitRunnerWrapper, nullptr), 0);
481 
482   // Wait for child able to receive signals.
483   ASSERT_EQ(sem_wait(&g_kill_and_wait_sem), 0);
484 
485   // If signal is successfully sent, child must handle it
486   // notifying parent with semaphore.
487   while (pthread_kill(child_id, SIGPWR) == 0) {
488     ASSERT_EQ(sem_wait(&g_kill_and_wait_sem), 0);
489   }
490 }
491 
492 std::atomic_bool g_is_in_loop;
493 std::atomic_bool g_is_received_in_loop;
494 
495 // POSIX recommends using itimerspec instead, but we don't support it in Berberis yet.
496 constexpr itimerval kTenMillisecondIntervalTimer = itimerval{
497     // Fire after 10 millisecond initially then every 10 millisecond further on (in case we haven't
498     // entered the loop when the first signal arrived).
499     .it_interval = {.tv_sec = 0, .tv_usec = 10000},
500     .it_value = {.tv_sec = 0, .tv_usec = 10000},
501 };
502 
InterruptLoopHandler(int signal)503 void InterruptLoopHandler(int signal) {
504   EXPECT_EQ(signal, SIGALRM);
505   g_is_received_in_loop = g_is_in_loop.load();
506 }
507 
InterruptLoopHelper(void (* LoopRunner)())508 void InterruptLoopHelper(void (*LoopRunner)()) {
509   struct sigaction sa {};
510   sa.sa_handler = InterruptLoopHandler;
511   ScopedSigaction scoped_sa(SIGALRM, &sa);
512 
513   g_is_in_loop = false;
514   g_is_received_in_loop = false;
515 
516   struct itimerval old_itimer;
517   setitimer(ITIMER_REAL, &kTenMillisecondIntervalTimer, &old_itimer);
518 
519   LoopRunner();
520 
521   setitimer(ITIMER_REAL, &old_itimer, nullptr);
522 }
523 
TEST(Signal,InterruptLoopWithinRegion)524 TEST(Signal, InterruptLoopWithinRegion) {
525   InterruptLoopHelper(+[]() {
526     while (!g_is_received_in_loop) {
527       // Keep it simple to facilitate having it in single translation region.
528       g_is_in_loop = true;
529     }
530   });
531 }
532 
RegionBreaker()533 void __attribute__((noinline)) RegionBreaker() {
534   g_is_in_loop = true;
535 }
536 
TEST(Signal,InterruptInterRegionLoop)537 TEST(Signal, InterruptInterRegionLoop) {
538   InterruptLoopHelper(+[]() {
539     while (!g_is_received_in_loop) {
540       // Facilitate translated regions break (due to call/return) so that the loop
541       // is not inside one region.
542       RegionBreaker();
543     }
544   });
545 }
546 
547 }  // namespace
548