• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016, 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 <err.h>
18 #include <fcntl.h>
19 #include <stdlib.h>
20 #include <sys/capability.h>
21 #include <sys/prctl.h>
22 #include <sys/ptrace.h>
23 #include <sys/resource.h>
24 #include <sys/syscall.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 
28 #include <chrono>
29 #include <regex>
30 #include <thread>
31 
32 #include <android/fdsan.h>
33 #include <android/set_abort_message.h>
34 
35 #include <android-base/cmsg.h>
36 #include <android-base/file.h>
37 #include <android-base/logging.h>
38 #include <android-base/macros.h>
39 #include <android-base/parseint.h>
40 #include <android-base/properties.h>
41 #include <android-base/stringprintf.h>
42 #include <android-base/strings.h>
43 #include <android-base/test_utils.h>
44 #include <android-base/unique_fd.h>
45 #include <cutils/sockets.h>
46 #include <gtest/gtest.h>
47 
48 #include <libminijail.h>
49 #include <scoped_minijail.h>
50 
51 #include "debuggerd/handler.h"
52 #include "protocol.h"
53 #include "tombstoned/tombstoned.h"
54 #include "util.h"
55 
56 using namespace std::chrono_literals;
57 
58 using android::base::SendFileDescriptors;
59 using android::base::unique_fd;
60 
61 #if defined(__LP64__)
62 #define ARCH_SUFFIX "64"
63 #else
64 #define ARCH_SUFFIX ""
65 #endif
66 
67 constexpr char kWaitForGdbKey[] = "debug.debuggerd.wait_for_gdb";
68 
69 #define TIMEOUT(seconds, expr)                                     \
70   [&]() {                                                          \
71     struct sigaction old_sigaction;                                \
72     struct sigaction new_sigaction = {};                           \
73     new_sigaction.sa_handler = [](int) {};                         \
74     if (sigaction(SIGALRM, &new_sigaction, &new_sigaction) != 0) { \
75       err(1, "sigaction failed");                                  \
76     }                                                              \
77     alarm(seconds);                                                \
78     auto value = expr;                                             \
79     int saved_errno = errno;                                       \
80     if (sigaction(SIGALRM, &old_sigaction, nullptr) != 0) {        \
81       err(1, "sigaction failed");                                  \
82     }                                                              \
83     alarm(0);                                                      \
84     errno = saved_errno;                                           \
85     return value;                                                  \
86   }()
87 
88 // Backtrace frame dump could contain:
89 //   #01 pc 0001cded  /data/tmp/debuggerd_test32 (raise_debugger_signal+80)
90 // or
91 //   #01 pc 00022a09  /data/tmp/debuggerd_test32 (offset 0x12000) (raise_debugger_signal+80)
92 #define ASSERT_BACKTRACE_FRAME(result, frame_name) \
93   ASSERT_MATCH(result,                             \
94                R"(#\d\d pc [0-9a-f]+\s+ \S+ (\(offset 0x[0-9a-f]+\) )?\()" frame_name R"(\+)");
95 
tombstoned_intercept(pid_t target_pid,unique_fd * intercept_fd,unique_fd * output_fd,InterceptStatus * status,DebuggerdDumpType intercept_type)96 static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, unique_fd* output_fd,
97                                  InterceptStatus* status, DebuggerdDumpType intercept_type) {
98   intercept_fd->reset(socket_local_client(kTombstonedInterceptSocketName,
99                                           ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
100   if (intercept_fd->get() == -1) {
101     FAIL() << "failed to contact tombstoned: " << strerror(errno);
102   }
103 
104   InterceptRequest req = {.pid = target_pid, .dump_type = intercept_type};
105 
106   unique_fd output_pipe_write;
107   if (!Pipe(output_fd, &output_pipe_write)) {
108     FAIL() << "failed to create output pipe: " << strerror(errno);
109   }
110 
111   std::string pipe_size_str;
112   int pipe_buffer_size;
113   if (!android::base::ReadFileToString("/proc/sys/fs/pipe-max-size", &pipe_size_str)) {
114     FAIL() << "failed to read /proc/sys/fs/pipe-max-size: " << strerror(errno);
115   }
116 
117   pipe_size_str = android::base::Trim(pipe_size_str);
118 
119   if (!android::base::ParseInt(pipe_size_str.c_str(), &pipe_buffer_size, 0)) {
120     FAIL() << "failed to parse pipe max size";
121   }
122 
123   if (fcntl(output_fd->get(), F_SETPIPE_SZ, pipe_buffer_size) != pipe_buffer_size) {
124     FAIL() << "failed to set pipe size: " << strerror(errno);
125   }
126 
127   ASSERT_GE(pipe_buffer_size, 1024 * 1024);
128 
129   ssize_t rc = SendFileDescriptors(intercept_fd->get(), &req, sizeof(req), output_pipe_write.get());
130   output_pipe_write.reset();
131   if (rc != sizeof(req)) {
132     FAIL() << "failed to send output fd to tombstoned: " << strerror(errno);
133   }
134 
135   InterceptResponse response;
136   rc = TEMP_FAILURE_RETRY(read(intercept_fd->get(), &response, sizeof(response)));
137   if (rc == -1) {
138     FAIL() << "failed to read response from tombstoned: " << strerror(errno);
139   } else if (rc == 0) {
140     FAIL() << "failed to read response from tombstoned (EOF)";
141   } else if (rc != sizeof(response)) {
142     FAIL() << "received packet of unexpected length from tombstoned: expected " << sizeof(response)
143            << ", received " << rc;
144   }
145 
146   *status = response.status;
147 }
148 
149 class CrasherTest : public ::testing::Test {
150  public:
151   pid_t crasher_pid = -1;
152   bool previous_wait_for_gdb;
153   unique_fd crasher_pipe;
154   unique_fd intercept_fd;
155 
156   CrasherTest();
157   ~CrasherTest();
158 
159   void StartIntercept(unique_fd* output_fd, DebuggerdDumpType intercept_type = kDebuggerdTombstone);
160 
161   // Returns -1 if we fail to read a response from tombstoned, otherwise the received return code.
162   void FinishIntercept(int* result);
163 
164   void StartProcess(std::function<void()> function, std::function<pid_t()> forker = fork);
165   void StartCrasher(const std::string& crash_type);
166   void FinishCrasher();
167   void AssertDeath(int signo);
168 };
169 
CrasherTest()170 CrasherTest::CrasherTest() {
171   previous_wait_for_gdb = android::base::GetBoolProperty(kWaitForGdbKey, false);
172   android::base::SetProperty(kWaitForGdbKey, "0");
173 }
174 
~CrasherTest()175 CrasherTest::~CrasherTest() {
176   if (crasher_pid != -1) {
177     kill(crasher_pid, SIGKILL);
178     int status;
179     waitpid(crasher_pid, &status, WUNTRACED);
180   }
181 
182   android::base::SetProperty(kWaitForGdbKey, previous_wait_for_gdb ? "1" : "0");
183 }
184 
StartIntercept(unique_fd * output_fd,DebuggerdDumpType intercept_type)185 void CrasherTest::StartIntercept(unique_fd* output_fd, DebuggerdDumpType intercept_type) {
186   if (crasher_pid == -1) {
187     FAIL() << "crasher hasn't been started";
188   }
189 
190   InterceptStatus status;
191   tombstoned_intercept(crasher_pid, &this->intercept_fd, output_fd, &status, intercept_type);
192   ASSERT_EQ(InterceptStatus::kRegistered, status);
193 }
194 
FinishIntercept(int * result)195 void CrasherTest::FinishIntercept(int* result) {
196   InterceptResponse response;
197 
198   // Timeout for tombstoned intercept is 10 seconds.
199   ssize_t rc = TIMEOUT(20, read(intercept_fd.get(), &response, sizeof(response)));
200   if (rc == -1) {
201     FAIL() << "failed to read response from tombstoned: " << strerror(errno);
202   } else if (rc == 0) {
203     *result = -1;
204   } else if (rc != sizeof(response)) {
205     FAIL() << "received packet of unexpected length from tombstoned: expected " << sizeof(response)
206            << ", received " << rc;
207   } else {
208     *result = response.status == InterceptStatus::kStarted ? 1 : 0;
209   }
210 }
211 
StartProcess(std::function<void ()> function,std::function<pid_t ()> forker)212 void CrasherTest::StartProcess(std::function<void()> function, std::function<pid_t()> forker) {
213   unique_fd read_pipe;
214   unique_fd crasher_read_pipe;
215   if (!Pipe(&crasher_read_pipe, &crasher_pipe)) {
216     FAIL() << "failed to create pipe: " << strerror(errno);
217   }
218 
219   crasher_pid = forker();
220   if (crasher_pid == -1) {
221     FAIL() << "fork failed: " << strerror(errno);
222   } else if (crasher_pid == 0) {
223     char dummy;
224     crasher_pipe.reset();
225     TEMP_FAILURE_RETRY(read(crasher_read_pipe.get(), &dummy, 1));
226     function();
227     _exit(0);
228   }
229 }
230 
FinishCrasher()231 void CrasherTest::FinishCrasher() {
232   if (crasher_pipe == -1) {
233     FAIL() << "crasher pipe uninitialized";
234   }
235 
236   ssize_t rc = write(crasher_pipe.get(), "\n", 1);
237   if (rc == -1) {
238     FAIL() << "failed to write to crasher pipe: " << strerror(errno);
239   } else if (rc == 0) {
240     FAIL() << "crasher pipe was closed";
241   }
242 }
243 
AssertDeath(int signo)244 void CrasherTest::AssertDeath(int signo) {
245   int status;
246   pid_t pid = TIMEOUT(5, waitpid(crasher_pid, &status, 0));
247   if (pid != crasher_pid) {
248     printf("failed to wait for crasher (pid %d)\n", crasher_pid);
249     sleep(100);
250     FAIL() << "failed to wait for crasher: " << strerror(errno);
251   }
252 
253   if (signo == 0) {
254     ASSERT_TRUE(WIFEXITED(status));
255     ASSERT_EQ(0, WEXITSTATUS(signo));
256   } else {
257     ASSERT_FALSE(WIFEXITED(status));
258     ASSERT_TRUE(WIFSIGNALED(status)) << "crasher didn't terminate via a signal";
259     ASSERT_EQ(signo, WTERMSIG(status));
260   }
261   crasher_pid = -1;
262 }
263 
ConsumeFd(unique_fd fd,std::string * output)264 static void ConsumeFd(unique_fd fd, std::string* output) {
265   constexpr size_t read_length = PAGE_SIZE;
266   std::string result;
267 
268   while (true) {
269     size_t offset = result.size();
270     result.resize(result.size() + PAGE_SIZE);
271     ssize_t rc = TEMP_FAILURE_RETRY(read(fd.get(), &result[offset], read_length));
272     if (rc == -1) {
273       FAIL() << "read failed: " << strerror(errno);
274     } else if (rc == 0) {
275       result.resize(result.size() - PAGE_SIZE);
276       break;
277     }
278 
279     result.resize(result.size() - PAGE_SIZE + rc);
280   }
281 
282   *output = std::move(result);
283 }
284 
TEST_F(CrasherTest,smoke)285 TEST_F(CrasherTest, smoke) {
286   int intercept_result;
287   unique_fd output_fd;
288   StartProcess([]() {
289     *reinterpret_cast<volatile char*>(0xdead) = '1';
290   });
291 
292   StartIntercept(&output_fd);
293   FinishCrasher();
294   AssertDeath(SIGSEGV);
295   FinishIntercept(&intercept_result);
296 
297   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
298 
299   std::string result;
300   ConsumeFd(std::move(output_fd), &result);
301   ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0xdead)");
302 }
303 
TEST_F(CrasherTest,LD_PRELOAD)304 TEST_F(CrasherTest, LD_PRELOAD) {
305   int intercept_result;
306   unique_fd output_fd;
307   StartProcess([]() {
308     setenv("LD_PRELOAD", "nonexistent.so", 1);
309     *reinterpret_cast<volatile char*>(0xdead) = '1';
310   });
311 
312   StartIntercept(&output_fd);
313   FinishCrasher();
314   AssertDeath(SIGSEGV);
315   FinishIntercept(&intercept_result);
316 
317   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
318 
319   std::string result;
320   ConsumeFd(std::move(output_fd), &result);
321   ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0xdead)");
322 }
323 
TEST_F(CrasherTest,abort)324 TEST_F(CrasherTest, abort) {
325   int intercept_result;
326   unique_fd output_fd;
327   StartProcess([]() {
328     abort();
329   });
330   StartIntercept(&output_fd);
331   FinishCrasher();
332   AssertDeath(SIGABRT);
333   FinishIntercept(&intercept_result);
334 
335   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
336 
337   std::string result;
338   ConsumeFd(std::move(output_fd), &result);
339   ASSERT_BACKTRACE_FRAME(result, "abort");
340 }
341 
TEST_F(CrasherTest,signal)342 TEST_F(CrasherTest, signal) {
343   int intercept_result;
344   unique_fd output_fd;
345   StartProcess([]() {
346     while (true) {
347       sleep(1);
348     }
349   });
350   StartIntercept(&output_fd);
351   FinishCrasher();
352   ASSERT_EQ(0, kill(crasher_pid, SIGSEGV));
353 
354   AssertDeath(SIGSEGV);
355   FinishIntercept(&intercept_result);
356 
357   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
358 
359   std::string result;
360   ConsumeFd(std::move(output_fd), &result);
361   ASSERT_MATCH(
362       result,
363       R"(signal 11 \(SIGSEGV\), code 0 \(SI_USER from pid \d+, uid \d+\), fault addr --------)");
364   ASSERT_MATCH(result, R"(backtrace:)");
365 }
366 
TEST_F(CrasherTest,abort_message)367 TEST_F(CrasherTest, abort_message) {
368   int intercept_result;
369   unique_fd output_fd;
370   StartProcess([]() {
371     // Arrived at experimentally;
372     // logd truncates at 4062.
373     // strlen("Abort message: ''") is 17.
374     // That's 4045, but we also want a NUL.
375     char buf[4045 + 1];
376     memset(buf, 'x', sizeof(buf));
377     buf[sizeof(buf) - 1] = '\0';
378     android_set_abort_message(buf);
379     abort();
380   });
381   StartIntercept(&output_fd);
382   FinishCrasher();
383   AssertDeath(SIGABRT);
384   FinishIntercept(&intercept_result);
385 
386   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
387 
388   std::string result;
389   ConsumeFd(std::move(output_fd), &result);
390   ASSERT_MATCH(result, R"(Abort message: 'x{4045}')");
391 }
392 
TEST_F(CrasherTest,abort_message_backtrace)393 TEST_F(CrasherTest, abort_message_backtrace) {
394   int intercept_result;
395   unique_fd output_fd;
396   StartProcess([]() {
397     android_set_abort_message("not actually aborting");
398     raise(DEBUGGER_SIGNAL);
399     exit(0);
400   });
401   StartIntercept(&output_fd);
402   FinishCrasher();
403   AssertDeath(0);
404   FinishIntercept(&intercept_result);
405 
406   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
407 
408   std::string result;
409   ConsumeFd(std::move(output_fd), &result);
410   ASSERT_NOT_MATCH(result, R"(Abort message:)");
411 }
412 
TEST_F(CrasherTest,intercept_timeout)413 TEST_F(CrasherTest, intercept_timeout) {
414   int intercept_result;
415   unique_fd output_fd;
416   StartProcess([]() {
417     abort();
418   });
419   StartIntercept(&output_fd);
420 
421   // Don't let crasher finish until we timeout.
422   FinishIntercept(&intercept_result);
423 
424   ASSERT_NE(1, intercept_result) << "tombstoned reported success? (intercept_result = "
425                                  << intercept_result << ")";
426 
427   FinishCrasher();
428   AssertDeath(SIGABRT);
429 }
430 
TEST_F(CrasherTest,wait_for_gdb)431 TEST_F(CrasherTest, wait_for_gdb) {
432   if (!android::base::SetProperty(kWaitForGdbKey, "1")) {
433     FAIL() << "failed to enable wait_for_gdb";
434   }
435   sleep(1);
436 
437   StartProcess([]() {
438     abort();
439   });
440   FinishCrasher();
441 
442   int status;
443   ASSERT_EQ(crasher_pid, waitpid(crasher_pid, &status, WUNTRACED));
444   ASSERT_TRUE(WIFSTOPPED(status));
445   ASSERT_EQ(SIGSTOP, WSTOPSIG(status));
446 
447   ASSERT_EQ(0, kill(crasher_pid, SIGCONT));
448 
449   AssertDeath(SIGABRT);
450 }
451 
TEST_F(CrasherTest,backtrace)452 TEST_F(CrasherTest, backtrace) {
453   std::string result;
454   int intercept_result;
455   unique_fd output_fd;
456 
457   StartProcess([]() {
458     abort();
459   });
460   StartIntercept(&output_fd, kDebuggerdNativeBacktrace);
461 
462   std::this_thread::sleep_for(500ms);
463 
464   sigval val;
465   val.sival_int = 1;
466   ASSERT_EQ(0, sigqueue(crasher_pid, DEBUGGER_SIGNAL, val)) << strerror(errno);
467   FinishIntercept(&intercept_result);
468   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
469   ConsumeFd(std::move(output_fd), &result);
470   ASSERT_BACKTRACE_FRAME(result, "read");
471 
472   int status;
473   ASSERT_EQ(0, waitpid(crasher_pid, &status, WNOHANG | WUNTRACED));
474 
475   StartIntercept(&output_fd);
476   FinishCrasher();
477   AssertDeath(SIGABRT);
478   FinishIntercept(&intercept_result);
479   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
480   ConsumeFd(std::move(output_fd), &result);
481   ASSERT_BACKTRACE_FRAME(result, "abort");
482 }
483 
TEST_F(CrasherTest,PR_SET_DUMPABLE_0_crash)484 TEST_F(CrasherTest, PR_SET_DUMPABLE_0_crash) {
485   int intercept_result;
486   unique_fd output_fd;
487   StartProcess([]() {
488     prctl(PR_SET_DUMPABLE, 0);
489     abort();
490   });
491 
492   StartIntercept(&output_fd);
493   FinishCrasher();
494   AssertDeath(SIGABRT);
495   FinishIntercept(&intercept_result);
496 
497   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
498 
499   std::string result;
500   ConsumeFd(std::move(output_fd), &result);
501   ASSERT_BACKTRACE_FRAME(result, "abort");
502 }
503 
TEST_F(CrasherTest,capabilities)504 TEST_F(CrasherTest, capabilities) {
505   ASSERT_EQ(0U, getuid()) << "capability test requires root";
506 
507   StartProcess([]() {
508     if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
509       err(1, "failed to set PR_SET_KEEPCAPS");
510     }
511 
512     if (setresuid(1, 1, 1) != 0) {
513       err(1, "setresuid failed");
514     }
515 
516     __user_cap_header_struct capheader;
517     __user_cap_data_struct capdata[2];
518     memset(&capheader, 0, sizeof(capheader));
519     memset(&capdata, 0, sizeof(capdata));
520 
521     capheader.version = _LINUX_CAPABILITY_VERSION_3;
522     capheader.pid = 0;
523 
524     // Turn on every third capability.
525     static_assert(CAP_LAST_CAP > 33, "CAP_LAST_CAP <= 32");
526     for (int i = 0; i < CAP_LAST_CAP; i += 3) {
527       capdata[CAP_TO_INDEX(i)].permitted |= CAP_TO_MASK(i);
528       capdata[CAP_TO_INDEX(i)].effective |= CAP_TO_MASK(i);
529     }
530 
531     // Make sure CAP_SYS_PTRACE is off.
532     capdata[CAP_TO_INDEX(CAP_SYS_PTRACE)].permitted &= ~(CAP_TO_MASK(CAP_SYS_PTRACE));
533     capdata[CAP_TO_INDEX(CAP_SYS_PTRACE)].effective &= ~(CAP_TO_MASK(CAP_SYS_PTRACE));
534 
535     if (capset(&capheader, &capdata[0]) != 0) {
536       err(1, "capset failed");
537     }
538 
539     if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0) != 0) {
540       err(1, "failed to drop ambient capabilities");
541     }
542 
543     pthread_setname_np(pthread_self(), "thread_name");
544     raise(SIGSYS);
545   });
546 
547   unique_fd output_fd;
548   StartIntercept(&output_fd);
549   FinishCrasher();
550   AssertDeath(SIGSYS);
551 
552   std::string result;
553   int intercept_result;
554   FinishIntercept(&intercept_result);
555   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
556   ConsumeFd(std::move(output_fd), &result);
557   ASSERT_MATCH(result, R"(name: thread_name\s+>>> .+debuggerd_test(32|64) <<<)");
558   ASSERT_BACKTRACE_FRAME(result, "tgkill");
559 }
560 
TEST_F(CrasherTest,fake_pid)561 TEST_F(CrasherTest, fake_pid) {
562   int intercept_result;
563   unique_fd output_fd;
564 
565   // Prime the getpid/gettid caches.
566   UNUSED(getpid());
567   UNUSED(gettid());
568 
569   std::function<pid_t()> clone_fn = []() {
570     return syscall(__NR_clone, SIGCHLD, nullptr, nullptr, nullptr, nullptr);
571   };
572   StartProcess(
573       []() {
574         ASSERT_NE(getpid(), syscall(__NR_getpid));
575         ASSERT_NE(gettid(), syscall(__NR_gettid));
576         raise(SIGSEGV);
577       },
578       clone_fn);
579 
580   StartIntercept(&output_fd);
581   FinishCrasher();
582   AssertDeath(SIGSEGV);
583   FinishIntercept(&intercept_result);
584 
585   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
586 
587   std::string result;
588   ConsumeFd(std::move(output_fd), &result);
589   ASSERT_BACKTRACE_FRAME(result, "tgkill");
590 }
591 
592 static const char* const kDebuggerdSeccompPolicy =
593     "/system/etc/seccomp_policy/crash_dump." ABI_STRING ".policy";
594 
seccomp_fork_impl(void (* prejail)())595 static pid_t seccomp_fork_impl(void (*prejail)()) {
596   std::string policy;
597   if (!android::base::ReadFileToString(kDebuggerdSeccompPolicy, &policy)) {
598     PLOG(FATAL) << "failed to read policy file";
599   }
600 
601   // Allow a bunch of syscalls used by the tests.
602   policy += "\nclone: 1";
603   policy += "\nsigaltstack: 1";
604   policy += "\nnanosleep: 1";
605 
606   FILE* tmp_file = tmpfile();
607   if (!tmp_file) {
608     PLOG(FATAL) << "tmpfile failed";
609   }
610 
611   unique_fd tmp_fd(dup(fileno(tmp_file)));
612   if (!android::base::WriteStringToFd(policy, tmp_fd.get())) {
613     PLOG(FATAL) << "failed to write policy to tmpfile";
614   }
615 
616   if (lseek(tmp_fd.get(), 0, SEEK_SET) != 0) {
617     PLOG(FATAL) << "failed to seek tmp_fd";
618   }
619 
620   ScopedMinijail jail{minijail_new()};
621   if (!jail) {
622     LOG(FATAL) << "failed to create minijail";
623   }
624 
625   minijail_no_new_privs(jail.get());
626   minijail_log_seccomp_filter_failures(jail.get());
627   minijail_use_seccomp_filter(jail.get());
628   minijail_parse_seccomp_filters_from_fd(jail.get(), tmp_fd.release());
629 
630   pid_t result = fork();
631   if (result == -1) {
632     return result;
633   } else if (result != 0) {
634     return result;
635   }
636 
637   // Spawn and detach a thread that spins forever.
638   std::atomic<bool> thread_ready(false);
639   std::thread thread([&jail, &thread_ready]() {
640     minijail_enter(jail.get());
641     thread_ready = true;
642     for (;;)
643       ;
644   });
645   thread.detach();
646 
647   while (!thread_ready) {
648     continue;
649   }
650 
651   if (prejail) {
652     prejail();
653   }
654 
655   minijail_enter(jail.get());
656   return result;
657 }
658 
seccomp_fork()659 static pid_t seccomp_fork() {
660   return seccomp_fork_impl(nullptr);
661 }
662 
TEST_F(CrasherTest,seccomp_crash)663 TEST_F(CrasherTest, seccomp_crash) {
664   int intercept_result;
665   unique_fd output_fd;
666 
667   StartProcess([]() { abort(); }, &seccomp_fork);
668 
669   StartIntercept(&output_fd);
670   FinishCrasher();
671   AssertDeath(SIGABRT);
672   FinishIntercept(&intercept_result);
673   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
674 
675   std::string result;
676   ConsumeFd(std::move(output_fd), &result);
677   ASSERT_BACKTRACE_FRAME(result, "abort");
678 }
679 
seccomp_fork_rlimit()680 static pid_t seccomp_fork_rlimit() {
681   return seccomp_fork_impl([]() {
682     struct rlimit rlim = {
683         .rlim_cur = 512 * 1024 * 1024,
684         .rlim_max = 512 * 1024 * 1024,
685     };
686 
687     if (setrlimit(RLIMIT_AS, &rlim) != 0) {
688       raise(SIGINT);
689     }
690   });
691 }
692 
TEST_F(CrasherTest,seccomp_crash_oom)693 TEST_F(CrasherTest, seccomp_crash_oom) {
694   int intercept_result;
695   unique_fd output_fd;
696 
697   StartProcess(
698       []() {
699         std::vector<void*> vec;
700         for (int i = 0; i < 512; ++i) {
701           char* buf = static_cast<char*>(malloc(1024 * 1024));
702           if (!buf) {
703             abort();
704           }
705           memset(buf, 0xff, 1024 * 1024);
706           vec.push_back(buf);
707         }
708       },
709       &seccomp_fork_rlimit);
710 
711   StartIntercept(&output_fd);
712   FinishCrasher();
713   AssertDeath(SIGABRT);
714   FinishIntercept(&intercept_result);
715   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
716 
717   // We can't actually generate a backtrace, just make sure that the process terminates.
718 }
719 
raise_debugger_signal(DebuggerdDumpType dump_type)720 __attribute__((noinline)) extern "C" bool raise_debugger_signal(DebuggerdDumpType dump_type) {
721   siginfo_t siginfo;
722   siginfo.si_code = SI_QUEUE;
723   siginfo.si_pid = getpid();
724   siginfo.si_uid = getuid();
725 
726   if (dump_type != kDebuggerdNativeBacktrace && dump_type != kDebuggerdTombstone) {
727     PLOG(FATAL) << "invalid dump type";
728   }
729 
730   siginfo.si_value.sival_int = dump_type == kDebuggerdNativeBacktrace;
731 
732   if (syscall(__NR_rt_tgsigqueueinfo, getpid(), gettid(), DEBUGGER_SIGNAL, &siginfo) != 0) {
733     PLOG(ERROR) << "libdebuggerd_client: failed to send signal to self";
734     return false;
735   }
736 
737   return true;
738 }
739 
TEST_F(CrasherTest,seccomp_tombstone)740 TEST_F(CrasherTest, seccomp_tombstone) {
741   int intercept_result;
742   unique_fd output_fd;
743 
744   static const auto dump_type = kDebuggerdTombstone;
745   StartProcess(
746       []() {
747         raise_debugger_signal(dump_type);
748         _exit(0);
749       },
750       &seccomp_fork);
751 
752   StartIntercept(&output_fd, dump_type);
753   FinishCrasher();
754   AssertDeath(0);
755   FinishIntercept(&intercept_result);
756   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
757 
758   std::string result;
759   ConsumeFd(std::move(output_fd), &result);
760   ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
761 }
762 
foo()763 extern "C" void foo() {
764   LOG(INFO) << "foo";
765   std::this_thread::sleep_for(1s);
766 }
767 
bar()768 extern "C" void bar() {
769   LOG(INFO) << "bar";
770   std::this_thread::sleep_for(1s);
771 }
772 
TEST_F(CrasherTest,seccomp_backtrace)773 TEST_F(CrasherTest, seccomp_backtrace) {
774   int intercept_result;
775   unique_fd output_fd;
776 
777   static const auto dump_type = kDebuggerdNativeBacktrace;
778   StartProcess(
779       []() {
780         std::thread a(foo);
781         std::thread b(bar);
782 
783         std::this_thread::sleep_for(100ms);
784 
785         raise_debugger_signal(dump_type);
786         _exit(0);
787       },
788       &seccomp_fork);
789 
790   StartIntercept(&output_fd, dump_type);
791   FinishCrasher();
792   AssertDeath(0);
793   FinishIntercept(&intercept_result);
794   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
795 
796   std::string result;
797   ConsumeFd(std::move(output_fd), &result);
798   ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
799   ASSERT_BACKTRACE_FRAME(result, "foo");
800   ASSERT_BACKTRACE_FRAME(result, "bar");
801 }
802 
TEST_F(CrasherTest,seccomp_crash_logcat)803 TEST_F(CrasherTest, seccomp_crash_logcat) {
804   StartProcess([]() { abort(); }, &seccomp_fork);
805   FinishCrasher();
806 
807   // Make sure we don't get SIGSYS when trying to dump a crash to logcat.
808   AssertDeath(SIGABRT);
809 }
810 
TEST_F(CrasherTest,competing_tracer)811 TEST_F(CrasherTest, competing_tracer) {
812   int intercept_result;
813   unique_fd output_fd;
814   StartProcess([]() {
815     raise(SIGABRT);
816   });
817 
818   StartIntercept(&output_fd);
819 
820   ASSERT_EQ(0, ptrace(PTRACE_SEIZE, crasher_pid, 0, 0));
821   FinishCrasher();
822 
823   int status;
824   ASSERT_EQ(crasher_pid, waitpid(crasher_pid, &status, 0));
825   ASSERT_TRUE(WIFSTOPPED(status));
826   ASSERT_EQ(SIGABRT, WSTOPSIG(status));
827 
828   ASSERT_EQ(0, ptrace(PTRACE_CONT, crasher_pid, 0, SIGABRT));
829   FinishIntercept(&intercept_result);
830   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
831 
832   std::string result;
833   ConsumeFd(std::move(output_fd), &result);
834   std::string regex = R"(failed to attach to thread \d+, already traced by )";
835   regex += std::to_string(gettid());
836   regex += R"( \(.+debuggerd_test)";
837   ASSERT_MATCH(result, regex.c_str());
838 
839   ASSERT_EQ(crasher_pid, waitpid(crasher_pid, &status, 0));
840   ASSERT_TRUE(WIFSTOPPED(status));
841   ASSERT_EQ(SIGABRT, WSTOPSIG(status));
842 
843   ASSERT_EQ(0, ptrace(PTRACE_DETACH, crasher_pid, 0, SIGABRT));
844   AssertDeath(SIGABRT);
845 }
846 
TEST_F(CrasherTest,fdsan_warning_abort_message)847 TEST_F(CrasherTest, fdsan_warning_abort_message) {
848   int intercept_result;
849   unique_fd output_fd;
850 
851   StartProcess([]() {
852     android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
853     unique_fd fd(open("/dev/null", O_RDONLY | O_CLOEXEC));
854     if (fd == -1) {
855       abort();
856     }
857     close(fd.get());
858     _exit(0);
859   });
860 
861   StartIntercept(&output_fd);
862   FinishCrasher();
863   AssertDeath(0);
864   FinishIntercept(&intercept_result);
865   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
866 
867   std::string result;
868   ConsumeFd(std::move(output_fd), &result);
869   ASSERT_MATCH(result, "Abort message: 'attempted to close");
870 }
871 
TEST(crash_dump,zombie)872 TEST(crash_dump, zombie) {
873   pid_t forkpid = fork();
874 
875   pid_t rc;
876   int status;
877 
878   if (forkpid == 0) {
879     errno = 0;
880     rc = waitpid(-1, &status, WNOHANG | __WALL | __WNOTHREAD);
881     if (rc != -1 || errno != ECHILD) {
882       errx(2, "first waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
883     }
884 
885     raise(DEBUGGER_SIGNAL);
886 
887     errno = 0;
888     rc = waitpid(-1, &status, __WALL | __WNOTHREAD);
889     if (rc != -1 || errno != ECHILD) {
890       errx(2, "second waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
891     }
892     _exit(0);
893   } else {
894     rc = waitpid(forkpid, &status, 0);
895     ASSERT_EQ(forkpid, rc);
896     ASSERT_TRUE(WIFEXITED(status));
897     ASSERT_EQ(0, WEXITSTATUS(status));
898   }
899 }
900 
TEST(tombstoned,no_notify)901 TEST(tombstoned, no_notify) {
902   // Do this a few times.
903   for (int i = 0; i < 3; ++i) {
904     pid_t pid = 123'456'789 + i;
905 
906     unique_fd intercept_fd, output_fd;
907     InterceptStatus status;
908     tombstoned_intercept(pid, &intercept_fd, &output_fd, &status, kDebuggerdTombstone);
909     ASSERT_EQ(InterceptStatus::kRegistered, status);
910 
911     {
912       unique_fd tombstoned_socket, input_fd;
913       ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
914       ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid)));
915     }
916 
917     pid_t read_pid;
918     ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid)));
919     ASSERT_EQ(read_pid, pid);
920   }
921 }
922 
TEST(tombstoned,stress)923 TEST(tombstoned, stress) {
924   // Spawn threads to simultaneously do a bunch of failing dumps and a bunch of successful dumps.
925   static constexpr int kDumpCount = 100;
926 
927   std::atomic<bool> start(false);
928   std::vector<std::thread> threads;
929   threads.emplace_back([&start]() {
930     while (!start) {
931       continue;
932     }
933 
934     // Use a way out of range pid, to avoid stomping on an actual process.
935     pid_t pid_base = 1'000'000;
936 
937     for (int dump = 0; dump < kDumpCount; ++dump) {
938       pid_t pid = pid_base + dump;
939 
940       unique_fd intercept_fd, output_fd;
941       InterceptStatus status;
942       tombstoned_intercept(pid, &intercept_fd, &output_fd, &status, kDebuggerdTombstone);
943       ASSERT_EQ(InterceptStatus::kRegistered, status);
944 
945       // Pretend to crash, and then immediately close the socket.
946       unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName,
947                                            ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
948       if (sockfd == -1) {
949         FAIL() << "failed to connect to tombstoned: " << strerror(errno);
950       }
951       TombstonedCrashPacket packet = {};
952       packet.packet_type = CrashPacketType::kDumpRequest;
953       packet.packet.dump_request.pid = pid;
954       if (TEMP_FAILURE_RETRY(write(sockfd, &packet, sizeof(packet))) != sizeof(packet)) {
955         FAIL() << "failed to write to tombstoned: " << strerror(errno);
956       }
957 
958       continue;
959     }
960   });
961 
962   threads.emplace_back([&start]() {
963     while (!start) {
964       continue;
965     }
966 
967     // Use a way out of range pid, to avoid stomping on an actual process.
968     pid_t pid_base = 2'000'000;
969 
970     for (int dump = 0; dump < kDumpCount; ++dump) {
971       pid_t pid = pid_base + dump;
972 
973       unique_fd intercept_fd, output_fd;
974       InterceptStatus status;
975       tombstoned_intercept(pid, &intercept_fd, &output_fd, &status, kDebuggerdTombstone);
976       ASSERT_EQ(InterceptStatus::kRegistered, status);
977 
978       {
979         unique_fd tombstoned_socket, input_fd;
980         ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
981         ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid)));
982         tombstoned_notify_completion(tombstoned_socket.get());
983       }
984 
985       // TODO: Fix the race that requires this sleep.
986       std::this_thread::sleep_for(50ms);
987 
988       pid_t read_pid;
989       ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid)));
990       ASSERT_EQ(read_pid, pid);
991     }
992   });
993 
994   start = true;
995 
996   for (std::thread& thread : threads) {
997     thread.join();
998   }
999 }
1000 
TEST(tombstoned,java_trace_intercept_smoke)1001 TEST(tombstoned, java_trace_intercept_smoke) {
1002   // Using a "real" PID is a little dangerous here - if the test fails
1003   // or crashes, we might end up getting a bogus / unreliable stack
1004   // trace.
1005   const pid_t self = getpid();
1006 
1007   unique_fd intercept_fd, output_fd;
1008   InterceptStatus status;
1009   tombstoned_intercept(self, &intercept_fd, &output_fd, &status, kDebuggerdJavaBacktrace);
1010   ASSERT_EQ(InterceptStatus::kRegistered, status);
1011 
1012   // First connect to tombstoned requesting a native backtrace. This
1013   // should result in a "regular" FD and not the installed intercept.
1014   const char native[] = "native";
1015   unique_fd tombstoned_socket, input_fd;
1016   ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdNativeBacktrace));
1017   ASSERT_TRUE(android::base::WriteFully(input_fd.get(), native, sizeof(native)));
1018   tombstoned_notify_completion(tombstoned_socket.get());
1019 
1020   // Then, connect to tombstoned asking for a java backtrace. This *should*
1021   // trigger the intercept.
1022   const char java[] = "java";
1023   ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdJavaBacktrace));
1024   ASSERT_TRUE(android::base::WriteFully(input_fd.get(), java, sizeof(java)));
1025   tombstoned_notify_completion(tombstoned_socket.get());
1026 
1027   char outbuf[sizeof(java)];
1028   ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
1029   ASSERT_STREQ("java", outbuf);
1030 }
1031 
TEST(tombstoned,multiple_intercepts)1032 TEST(tombstoned, multiple_intercepts) {
1033   const pid_t fake_pid = 1'234'567;
1034   unique_fd intercept_fd, output_fd;
1035   InterceptStatus status;
1036   tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &status, kDebuggerdJavaBacktrace);
1037   ASSERT_EQ(InterceptStatus::kRegistered, status);
1038 
1039   unique_fd intercept_fd_2, output_fd_2;
1040   tombstoned_intercept(fake_pid, &intercept_fd_2, &output_fd_2, &status, kDebuggerdNativeBacktrace);
1041   ASSERT_EQ(InterceptStatus::kFailedAlreadyRegistered, status);
1042 }
1043 
TEST(tombstoned,intercept_any)1044 TEST(tombstoned, intercept_any) {
1045   const pid_t fake_pid = 1'234'567;
1046 
1047   unique_fd intercept_fd, output_fd;
1048   InterceptStatus status;
1049   tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &status, kDebuggerdNativeBacktrace);
1050   ASSERT_EQ(InterceptStatus::kRegistered, status);
1051 
1052   const char any[] = "any";
1053   unique_fd tombstoned_socket, input_fd;
1054   ASSERT_TRUE(tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdAnyIntercept));
1055   ASSERT_TRUE(android::base::WriteFully(input_fd.get(), any, sizeof(any)));
1056   tombstoned_notify_completion(tombstoned_socket.get());
1057 
1058   char outbuf[sizeof(any)];
1059   ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
1060   ASSERT_STREQ("any", outbuf);
1061 }
1062 
TEST(tombstoned,interceptless_backtrace)1063 TEST(tombstoned, interceptless_backtrace) {
1064   // Generate 50 backtraces, and then check to see that we haven't created 50 new tombstones.
1065   auto get_tombstone_timestamps = []() -> std::map<int, time_t> {
1066     std::map<int, time_t> result;
1067     for (int i = 0; i < 99; ++i) {
1068       std::string path = android::base::StringPrintf("/data/tombstones/tombstone_%02d", i);
1069       struct stat st;
1070       if (stat(path.c_str(), &st) == 0) {
1071         result[i] = st.st_mtim.tv_sec;
1072       }
1073     }
1074     return result;
1075   };
1076 
1077   auto before = get_tombstone_timestamps();
1078   for (int i = 0; i < 50; ++i) {
1079     raise_debugger_signal(kDebuggerdNativeBacktrace);
1080   }
1081   auto after = get_tombstone_timestamps();
1082 
1083   int diff = 0;
1084   for (int i = 0; i < 99; ++i) {
1085     if (after.count(i) == 0) {
1086       continue;
1087     }
1088     if (before.count(i) == 0) {
1089       ++diff;
1090       continue;
1091     }
1092     if (before[i] != after[i]) {
1093       ++diff;
1094     }
1095   }
1096 
1097   // We can't be sure that nothing's crash looping in the background.
1098   // This should be good enough, though...
1099   ASSERT_LT(diff, 10) << "too many new tombstones; is something crashing in the background?";
1100 }
1101