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 <dirent.h>
18 #include <dlfcn.h>
19 #include <err.h>
20 #include <fcntl.h>
21 #include <linux/prctl.h>
22 #include <malloc.h>
23 #include <pthread.h>
24 #include <stdlib.h>
25 #include <sys/capability.h>
26 #include <sys/mman.h>
27 #include <sys/prctl.h>
28 #include <sys/ptrace.h>
29 #include <sys/resource.h>
30 #include <sys/syscall.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33 
34 #include <chrono>
35 #include <regex>
36 #include <set>
37 #include <string>
38 #include <thread>
39 
40 #include <android/dlext.h>
41 #include <android/fdsan.h>
42 #include <android/set_abort_message.h>
43 #include <bionic/malloc.h>
44 #include <bionic/mte.h>
45 #include <bionic/reserved_signals.h>
46 
47 #include <android-base/cmsg.h>
48 #include <android-base/file.h>
49 #include <android-base/logging.h>
50 #include <android-base/macros.h>
51 #include <android-base/parseint.h>
52 #include <android-base/properties.h>
53 #include <android-base/stringprintf.h>
54 #include <android-base/strings.h>
55 #include <android-base/test_utils.h>
56 #include <android-base/unique_fd.h>
57 #include <cutils/sockets.h>
58 #include <gmock/gmock.h>
59 #include <gtest/gtest.h>
60 
61 #include <unwindstack/Elf.h>
62 #include <unwindstack/Memory.h>
63 
64 #include <libminijail.h>
65 #include <scoped_minijail.h>
66 
67 #include "crash_test.h"
68 #include "debuggerd/handler.h"
69 #include "gtest/gtest.h"
70 #include "libdebuggerd/utility.h"
71 #include "protocol.h"
72 #include "tombstoned/tombstoned.h"
73 #include "util.h"
74 
75 using namespace std::chrono_literals;
76 
77 using android::base::SendFileDescriptors;
78 using android::base::unique_fd;
79 using ::testing::HasSubstr;
80 
81 #if defined(__LP64__)
82 #define ARCH_SUFFIX "64"
83 #else
84 #define ARCH_SUFFIX ""
85 #endif
86 
87 constexpr char kWaitForDebuggerKey[] = "debug.debuggerd.wait_for_debugger";
88 
89 #define TIMEOUT(seconds, expr)                                     \
90   [&]() {                                                          \
91     struct sigaction old_sigaction;                                \
92     struct sigaction new_sigaction = {};                           \
93     new_sigaction.sa_handler = [](int) {};                         \
94     if (sigaction(SIGALRM, &new_sigaction, &old_sigaction) != 0) { \
95       err(1, "sigaction failed");                                  \
96     }                                                              \
97     alarm(seconds);                                                \
98     auto value = expr;                                             \
99     int saved_errno = errno;                                       \
100     if (sigaction(SIGALRM, &old_sigaction, nullptr) != 0) {        \
101       err(1, "sigaction failed");                                  \
102     }                                                              \
103     alarm(0);                                                      \
104     errno = saved_errno;                                           \
105     return value;                                                  \
106   }()
107 
108 // Backtrace frame dump could contain:
109 //   #01 pc 0001cded  /data/tmp/debuggerd_test32 (raise_debugger_signal+80)
110 // or
111 //   #01 pc 00022a09  /data/tmp/debuggerd_test32 (offset 0x12000) (raise_debugger_signal+80)
112 #define ASSERT_BACKTRACE_FRAME(result, frame_name) \
113   ASSERT_MATCH(result,                             \
114                R"(#\d\d pc [0-9a-f]+\s+ \S+ (\(offset 0x[0-9a-f]+\) )?\()" frame_name R"(\+)");
115 
tombstoned_intercept(pid_t target_pid,unique_fd * intercept_fd,unique_fd * output_fd,InterceptStatus * status,DebuggerdDumpType intercept_type)116 static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, unique_fd* output_fd,
117                                  InterceptStatus* status, DebuggerdDumpType intercept_type) {
118   intercept_fd->reset(socket_local_client(kTombstonedInterceptSocketName,
119                                           ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
120   if (intercept_fd->get() == -1) {
121     FAIL() << "failed to contact tombstoned: " << strerror(errno);
122   }
123 
124   InterceptRequest req = {
125       .dump_type = intercept_type,
126       .pid = target_pid,
127   };
128 
129   unique_fd output_pipe_write;
130   if (!Pipe(output_fd, &output_pipe_write)) {
131     FAIL() << "failed to create output pipe: " << strerror(errno);
132   }
133 
134   std::string pipe_size_str;
135   int pipe_buffer_size;
136   if (!android::base::ReadFileToString("/proc/sys/fs/pipe-max-size", &pipe_size_str)) {
137     FAIL() << "failed to read /proc/sys/fs/pipe-max-size: " << strerror(errno);
138   }
139 
140   pipe_size_str = android::base::Trim(pipe_size_str);
141 
142   if (!android::base::ParseInt(pipe_size_str.c_str(), &pipe_buffer_size, 0)) {
143     FAIL() << "failed to parse pipe max size";
144   }
145 
146   if (fcntl(output_fd->get(), F_SETPIPE_SZ, pipe_buffer_size) != pipe_buffer_size) {
147     FAIL() << "failed to set pipe size: " << strerror(errno);
148   }
149 
150   ASSERT_GE(pipe_buffer_size, 1024 * 1024);
151 
152   ssize_t rc = SendFileDescriptors(intercept_fd->get(), &req, sizeof(req), output_pipe_write.get());
153   output_pipe_write.reset();
154   if (rc != sizeof(req)) {
155     FAIL() << "failed to send output fd to tombstoned: " << strerror(errno);
156   }
157 
158   InterceptResponse response;
159   rc = TEMP_FAILURE_RETRY(read(intercept_fd->get(), &response, sizeof(response)));
160   if (rc == -1) {
161     FAIL() << "failed to read response from tombstoned: " << strerror(errno);
162   } else if (rc == 0) {
163     FAIL() << "failed to read response from tombstoned (EOF)";
164   } else if (rc != sizeof(response)) {
165     FAIL() << "received packet of unexpected length from tombstoned: expected " << sizeof(response)
166            << ", received " << rc;
167   }
168 
169   *status = response.status;
170 }
171 
pac_supported()172 static bool pac_supported() {
173 #if defined(__aarch64__)
174   return getauxval(AT_HWCAP) & HWCAP_PACA;
175 #else
176   return false;
177 #endif
178 }
179 
180 class CrasherTest : public ::testing::Test {
181  public:
182   pid_t crasher_pid = -1;
183   bool previous_wait_for_debugger;
184   unique_fd crasher_pipe;
185   unique_fd intercept_fd;
186 
187   CrasherTest();
188   ~CrasherTest();
189 
190   void StartIntercept(unique_fd* output_fd, DebuggerdDumpType intercept_type = kDebuggerdTombstone);
191 
192   // Returns -1 if we fail to read a response from tombstoned, otherwise the received return code.
193   void FinishIntercept(int* result);
194 
195   void StartProcess(std::function<void()> function, std::function<pid_t()> forker = fork);
196   void StartCrasher(const std::string& crash_type);
197   void FinishCrasher();
198   void AssertDeath(int signo);
199 
200   static void Trap(void* ptr);
201 };
202 
CrasherTest()203 CrasherTest::CrasherTest() {
204   previous_wait_for_debugger = android::base::GetBoolProperty(kWaitForDebuggerKey, false);
205   android::base::SetProperty(kWaitForDebuggerKey, "0");
206 
207   // Clear the old property too, just in case someone's been using it
208   // on this device. (We only document the new name, but we still support
209   // the old name so we don't break anyone's existing setups.)
210   android::base::SetProperty("debug.debuggerd.wait_for_gdb", "0");
211 }
212 
~CrasherTest()213 CrasherTest::~CrasherTest() {
214   if (crasher_pid != -1) {
215     kill(crasher_pid, SIGKILL);
216     int status;
217     TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, WUNTRACED));
218   }
219 
220   android::base::SetProperty(kWaitForDebuggerKey, previous_wait_for_debugger ? "1" : "0");
221 }
222 
StartIntercept(unique_fd * output_fd,DebuggerdDumpType intercept_type)223 void CrasherTest::StartIntercept(unique_fd* output_fd, DebuggerdDumpType intercept_type) {
224   if (crasher_pid == -1) {
225     FAIL() << "crasher hasn't been started";
226   }
227 
228   InterceptStatus status;
229   tombstoned_intercept(crasher_pid, &this->intercept_fd, output_fd, &status, intercept_type);
230   ASSERT_EQ(InterceptStatus::kRegistered, status);
231 }
232 
FinishIntercept(int * result)233 void CrasherTest::FinishIntercept(int* result) {
234   InterceptResponse response;
235 
236   ssize_t rc = TIMEOUT(30, read(intercept_fd.get(), &response, sizeof(response)));
237   if (rc == -1) {
238     FAIL() << "failed to read response from tombstoned: " << strerror(errno);
239   } else if (rc == 0) {
240     *result = -1;
241   } else if (rc != sizeof(response)) {
242     FAIL() << "received packet of unexpected length from tombstoned: expected " << sizeof(response)
243            << ", received " << rc;
244   } else {
245     *result = response.status == InterceptStatus::kStarted ? 1 : 0;
246   }
247 }
248 
StartProcess(std::function<void ()> function,std::function<pid_t ()> forker)249 void CrasherTest::StartProcess(std::function<void()> function, std::function<pid_t()> forker) {
250   unique_fd read_pipe;
251   unique_fd crasher_read_pipe;
252   if (!Pipe(&crasher_read_pipe, &crasher_pipe)) {
253     FAIL() << "failed to create pipe: " << strerror(errno);
254   }
255 
256   crasher_pid = forker();
257   if (crasher_pid == -1) {
258     FAIL() << "fork failed: " << strerror(errno);
259   } else if (crasher_pid == 0) {
260     char dummy;
261     crasher_pipe.reset();
262     TEMP_FAILURE_RETRY(read(crasher_read_pipe.get(), &dummy, 1));
263     function();
264     _exit(0);
265   }
266 }
267 
FinishCrasher()268 void CrasherTest::FinishCrasher() {
269   if (crasher_pipe == -1) {
270     FAIL() << "crasher pipe uninitialized";
271   }
272 
273   ssize_t rc = TEMP_FAILURE_RETRY(write(crasher_pipe.get(), "\n", 1));
274   if (rc == -1) {
275     FAIL() << "failed to write to crasher pipe: " << strerror(errno);
276   } else if (rc == 0) {
277     FAIL() << "crasher pipe was closed";
278   }
279 }
280 
AssertDeath(int signo)281 void CrasherTest::AssertDeath(int signo) {
282   int status;
283   pid_t pid = TIMEOUT(30, waitpid(crasher_pid, &status, 0));
284   if (pid != crasher_pid) {
285     printf("failed to wait for crasher (expected pid %d, return value %d): %s\n", crasher_pid, pid,
286            strerror(errno));
287     sleep(100);
288     FAIL() << "failed to wait for crasher: " << strerror(errno);
289   }
290 
291   if (signo == 0) {
292     ASSERT_TRUE(WIFEXITED(status)) << "Terminated due to unexpected signal " << WTERMSIG(status);
293     ASSERT_EQ(0, WEXITSTATUS(signo));
294   } else {
295     ASSERT_FALSE(WIFEXITED(status));
296     ASSERT_TRUE(WIFSIGNALED(status)) << "crasher didn't terminate via a signal";
297     ASSERT_EQ(signo, WTERMSIG(status));
298   }
299   crasher_pid = -1;
300 }
301 
ConsumeFd(unique_fd fd,std::string * output)302 static void ConsumeFd(unique_fd fd, std::string* output) {
303   constexpr size_t read_length = PAGE_SIZE;
304   std::string result;
305 
306   while (true) {
307     size_t offset = result.size();
308     result.resize(result.size() + PAGE_SIZE);
309     ssize_t rc = TEMP_FAILURE_RETRY(read(fd.get(), &result[offset], read_length));
310     if (rc == -1) {
311       FAIL() << "read failed: " << strerror(errno);
312     } else if (rc == 0) {
313       result.resize(result.size() - PAGE_SIZE);
314       break;
315     }
316 
317     result.resize(result.size() - PAGE_SIZE + rc);
318   }
319 
320   *output = std::move(result);
321 }
322 
323 class LogcatCollector {
324  public:
LogcatCollector()325   LogcatCollector() { system("logcat -c"); }
326 
Collect(std::string * output)327   void Collect(std::string* output) {
328     FILE* cmd_stdout = popen("logcat -d '*:S DEBUG'", "r");
329     ASSERT_NE(cmd_stdout, nullptr);
330     unique_fd tmp_fd(TEMP_FAILURE_RETRY(dup(fileno(cmd_stdout))));
331     ConsumeFd(std::move(tmp_fd), output);
332     pclose(cmd_stdout);
333   }
334 };
335 
TEST_F(CrasherTest,smoke)336 TEST_F(CrasherTest, smoke) {
337   int intercept_result;
338   unique_fd output_fd;
339   StartProcess([]() {
340     *reinterpret_cast<volatile char*>(0xdead) = '1';
341   });
342 
343   StartIntercept(&output_fd);
344   FinishCrasher();
345   AssertDeath(SIGSEGV);
346   FinishIntercept(&intercept_result);
347 
348   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
349 
350   std::string result;
351   ConsumeFd(std::move(output_fd), &result);
352 #ifdef __LP64__
353   ASSERT_MATCH(result,
354                R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x000000000000dead)");
355 #else
356   ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0000dead)");
357 #endif
358 
359   if (mte_supported()) {
360     // Test that the default TAGGED_ADDR_CTRL value is set.
361     ASSERT_MATCH(result, R"(tagged_addr_ctrl: 000000000007fff3)"
362                          R"( \(PR_TAGGED_ADDR_ENABLE, PR_MTE_TCF_SYNC, mask 0xfffe\))");
363   }
364 
365   if (pac_supported()) {
366     // Test that the default PAC_ENABLED_KEYS value is set.
367     ASSERT_MATCH(result, R"(pac_enabled_keys: 000000000000000f)"
368                          R"( \(PR_PAC_APIAKEY, PR_PAC_APIBKEY, PR_PAC_APDAKEY, PR_PAC_APDBKEY\))");
369   }
370 }
371 
TEST_F(CrasherTest,tagged_fault_addr)372 TEST_F(CrasherTest, tagged_fault_addr) {
373 #if !defined(__aarch64__)
374   GTEST_SKIP() << "Requires aarch64";
375 #endif
376   // HWASan crashes with SIGABRT on tag mismatch.
377   SKIP_WITH_HWASAN;
378   int intercept_result;
379   unique_fd output_fd;
380   StartProcess([]() {
381     *reinterpret_cast<volatile char*>(0x100000000000dead) = '1';
382   });
383 
384   StartIntercept(&output_fd);
385   FinishCrasher();
386   AssertDeath(SIGSEGV);
387   FinishIntercept(&intercept_result);
388 
389   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
390 
391   std::string result;
392   ConsumeFd(std::move(output_fd), &result);
393 
394   // The address can either be tagged (new kernels) or untagged (old kernels).
395   ASSERT_MATCH(
396       result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x[01]00000000000dead)");
397 }
398 
Trap(void * ptr)399 void CrasherTest::Trap(void* ptr) {
400   void (*volatile f)(void*) = nullptr;
401   __asm__ __volatile__("" : : "r"(f) : "memory");
402   f(ptr);
403 }
404 
TEST_F(CrasherTest,heap_addr_in_register)405 TEST_F(CrasherTest, heap_addr_in_register) {
406 #if defined(__i386__)
407   GTEST_SKIP() << "architecture does not pass arguments in registers";
408 #endif
409   // The memory dump in HWASan crashes sadly shows the memory near the registers
410   // in the HWASan dump function, rather the faulting context. This is a known
411   // issue.
412   SKIP_WITH_HWASAN;
413   int intercept_result;
414   unique_fd output_fd;
415   StartProcess([]() {
416     // Crash with a heap pointer in the first argument register.
417     Trap(malloc(1));
418   });
419 
420   StartIntercept(&output_fd);
421   FinishCrasher();
422   int status;
423   ASSERT_EQ(crasher_pid, TIMEOUT(30, waitpid(crasher_pid, &status, 0)));
424   ASSERT_TRUE(WIFSIGNALED(status)) << "crasher didn't terminate via a signal";
425   // Don't test the signal number because different architectures use different signals for
426   // __builtin_trap().
427   FinishIntercept(&intercept_result);
428 
429   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
430 
431   std::string result;
432   ConsumeFd(std::move(output_fd), &result);
433 
434 #if defined(__aarch64__)
435   ASSERT_MATCH(result, "memory near x0 \\(\\[anon:");
436 #elif defined(__arm__)
437   ASSERT_MATCH(result, "memory near r0 \\(\\[anon:");
438 #elif defined(__riscv)
439   ASSERT_MATCH(result, "memory near a0 \\(\\[anon:");
440 #elif defined(__x86_64__)
441   ASSERT_MATCH(result, "memory near rdi \\(\\[anon:");
442 #else
443   ASSERT_TRUE(false) << "unsupported architecture";
444 #endif
445 }
446 
447 #if defined(__aarch64__)
SetTagCheckingLevelSync()448 static void SetTagCheckingLevelSync() {
449   if (mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_SYNC) == 0) {
450     abort();
451   }
452 }
453 
SetTagCheckingLevelAsync()454 static void SetTagCheckingLevelAsync() {
455   if (mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_ASYNC) == 0) {
456     abort();
457   }
458 }
459 #endif
460 
461 struct SizeParamCrasherTest : CrasherTest, testing::WithParamInterface<size_t> {};
462 
463 INSTANTIATE_TEST_SUITE_P(Sizes, SizeParamCrasherTest, testing::Values(0, 16, 131072));
464 
TEST_P(SizeParamCrasherTest,mte_uaf)465 TEST_P(SizeParamCrasherTest, mte_uaf) {
466 #if defined(__aarch64__)
467   if (!mte_supported()) {
468     GTEST_SKIP() << "Requires MTE";
469   }
470 
471   // Any UAF on a zero-sized allocation will be out-of-bounds so it won't be reported.
472   if (GetParam() == 0) {
473     return;
474   }
475 
476   LogcatCollector logcat_collector;
477 
478   int intercept_result;
479   unique_fd output_fd;
480   StartProcess([&]() {
481     SetTagCheckingLevelSync();
482     volatile int* p = (volatile int*)malloc(GetParam());
483     free((void *)p);
484     p[0] = 42;
485   });
486 
487   StartIntercept(&output_fd);
488   FinishCrasher();
489   AssertDeath(SIGSEGV);
490   FinishIntercept(&intercept_result);
491 
492   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
493 
494   std::vector<std::string> log_sources(2);
495   ConsumeFd(std::move(output_fd), &log_sources[0]);
496   logcat_collector.Collect(&log_sources[1]);
497   // Tag dump only available in the tombstone, not logcat.
498   ASSERT_MATCH(log_sources[0], "Memory tags around the fault address");
499 
500   for (const auto& result : log_sources) {
501     ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
502     ASSERT_MATCH(result, R"(Cause: \[MTE\]: Use After Free, 0 bytes into a )" +
503                              std::to_string(GetParam()) + R"(-byte allocation)");
504     ASSERT_MATCH(result, R"(deallocated by thread .*?\n.*#00 pc)");
505     ASSERT_MATCH(result, R"((^|\s)allocated by thread .*?\n.*#00 pc)");
506   }
507 #else
508   GTEST_SKIP() << "Requires aarch64";
509 #endif
510 }
511 
TEST_P(SizeParamCrasherTest,mte_oob_uaf)512 TEST_P(SizeParamCrasherTest, mte_oob_uaf) {
513 #if defined(__aarch64__)
514   if (!mte_supported()) {
515     GTEST_SKIP() << "Requires MTE";
516   }
517 
518   int intercept_result;
519   unique_fd output_fd;
520   StartProcess([&]() {
521     SetTagCheckingLevelSync();
522     volatile int* p = (volatile int*)malloc(GetParam());
523     free((void *)p);
524     p[-1] = 42;
525   });
526 
527   StartIntercept(&output_fd);
528   FinishCrasher();
529   AssertDeath(SIGSEGV);
530   FinishIntercept(&intercept_result);
531 
532   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
533 
534   std::string result;
535   ConsumeFd(std::move(output_fd), &result);
536 
537   ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
538   ASSERT_NOT_MATCH(result, R"(Cause: \[MTE\]: Use After Free, 4 bytes left)");
539 #else
540   GTEST_SKIP() << "Requires aarch64";
541 #endif
542 }
543 
TEST_P(SizeParamCrasherTest,mte_overflow)544 TEST_P(SizeParamCrasherTest, mte_overflow) {
545 #if defined(__aarch64__)
546   if (!mte_supported()) {
547     GTEST_SKIP() << "Requires MTE";
548   }
549 
550   LogcatCollector logcat_collector;
551   int intercept_result;
552   unique_fd output_fd;
553   StartProcess([&]() {
554     SetTagCheckingLevelSync();
555     volatile char* p = (volatile char*)malloc(GetParam());
556     p[GetParam()] = 42;
557   });
558 
559   StartIntercept(&output_fd);
560   FinishCrasher();
561   AssertDeath(SIGSEGV);
562   FinishIntercept(&intercept_result);
563 
564   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
565 
566   std::vector<std::string> log_sources(2);
567   ConsumeFd(std::move(output_fd), &log_sources[0]);
568   logcat_collector.Collect(&log_sources[1]);
569 
570   // Tag dump only in tombstone, not logcat, and tagging is not used for
571   // overflow protection in the scudo secondary (guard pages are used instead).
572   if (GetParam() < 0x10000) {
573     ASSERT_MATCH(log_sources[0], "Memory tags around the fault address");
574   }
575 
576   for (const auto& result : log_sources) {
577     ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
578     ASSERT_MATCH(result, R"(Cause: \[MTE\]: Buffer Overflow, 0 bytes right of a )" +
579                              std::to_string(GetParam()) + R"(-byte allocation)");
580     ASSERT_MATCH(result, R"((^|\s)allocated by thread .*?\n.*#00 pc)");
581   }
582 #else
583   GTEST_SKIP() << "Requires aarch64";
584 #endif
585 }
586 
TEST_P(SizeParamCrasherTest,mte_underflow)587 TEST_P(SizeParamCrasherTest, mte_underflow) {
588 #if defined(__aarch64__)
589   if (!mte_supported()) {
590     GTEST_SKIP() << "Requires MTE";
591   }
592 
593   int intercept_result;
594   unique_fd output_fd;
595   StartProcess([&]() {
596     SetTagCheckingLevelSync();
597     volatile int* p = (volatile int*)malloc(GetParam());
598     p[-1] = 42;
599   });
600 
601   StartIntercept(&output_fd);
602   FinishCrasher();
603   AssertDeath(SIGSEGV);
604   FinishIntercept(&intercept_result);
605 
606   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
607 
608   std::string result;
609   ConsumeFd(std::move(output_fd), &result);
610 
611   ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 9 \(SEGV_MTESERR\))");
612   ASSERT_MATCH(result, R"(Cause: \[MTE\]: Buffer Underflow, 4 bytes left of a )" +
613                            std::to_string(GetParam()) + R"(-byte allocation)");
614   ASSERT_MATCH(result, R"((^|\s)allocated by thread .*
615       #00 pc)");
616   ASSERT_MATCH(result, "Memory tags around the fault address");
617 #else
618   GTEST_SKIP() << "Requires aarch64";
619 #endif
620 }
621 
TEST_F(CrasherTest,mte_async)622 TEST_F(CrasherTest, mte_async) {
623 #if defined(__aarch64__)
624   if (!mte_supported()) {
625     GTEST_SKIP() << "Requires MTE";
626   }
627 
628   int intercept_result;
629   unique_fd output_fd;
630   StartProcess([&]() {
631     SetTagCheckingLevelAsync();
632     volatile int* p = (volatile int*)malloc(16);
633     p[-1] = 42;
634   });
635 
636   StartIntercept(&output_fd);
637   FinishCrasher();
638   AssertDeath(SIGSEGV);
639   FinishIntercept(&intercept_result);
640 
641   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
642 
643   std::string result;
644   ConsumeFd(std::move(output_fd), &result);
645 
646   ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code [89] \(SEGV_MTE[AS]ERR\), fault addr)");
647 #else
648   GTEST_SKIP() << "Requires aarch64";
649 #endif
650 }
651 
TEST_F(CrasherTest,mte_multiple_causes)652 TEST_F(CrasherTest, mte_multiple_causes) {
653 #if defined(__aarch64__)
654   if (!mte_supported()) {
655     GTEST_SKIP() << "Requires MTE";
656   }
657 
658   LogcatCollector logcat_collector;
659 
660   int intercept_result;
661   unique_fd output_fd;
662   StartProcess([]() {
663     SetTagCheckingLevelSync();
664 
665     // Make two allocations with the same tag and close to one another. Check for both properties
666     // with a bounds check -- this relies on the fact that only if the allocations have the same tag
667     // would they be measured as closer than 128 bytes to each other. Otherwise they would be about
668     // (some non-zero value << 56) apart.
669     //
670     // The out-of-bounds access will be considered either an overflow of one or an underflow of the
671     // other.
672     std::set<uintptr_t> allocs;
673     for (int i = 0; i != 4096; ++i) {
674       uintptr_t alloc = reinterpret_cast<uintptr_t>(malloc(16));
675       auto it = allocs.insert(alloc).first;
676       if (it != allocs.begin() && *std::prev(it) + 128 > alloc) {
677         *reinterpret_cast<int*>(*std::prev(it) + 16) = 42;
678       }
679       if (std::next(it) != allocs.end() && alloc + 128 > *std::next(it)) {
680         *reinterpret_cast<int*>(alloc + 16) = 42;
681       }
682     }
683   });
684 
685   StartIntercept(&output_fd);
686   FinishCrasher();
687   AssertDeath(SIGSEGV);
688   FinishIntercept(&intercept_result);
689 
690   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
691 
692   std::vector<std::string> log_sources(2);
693   ConsumeFd(std::move(output_fd), &log_sources[0]);
694   logcat_collector.Collect(&log_sources[1]);
695 
696   // Tag dump only in the tombstone, not logcat.
697   ASSERT_MATCH(log_sources[0], "Memory tags around the fault address");
698 
699   for (const auto& result : log_sources) {
700     ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
701     ASSERT_THAT(result, HasSubstr("Note: multiple potential causes for this crash were detected, "
702                                   "listing them in decreasing order of likelihood."));
703     // Adjacent untracked allocations may cause us to see the wrong underflow here (or only
704     // overflows), so we can't match explicitly for an underflow message.
705     ASSERT_MATCH(result,
706                  R"(Cause: \[MTE\]: Buffer Overflow, 0 bytes right of a 16-byte allocation)");
707     // Ensure there's at least two allocation traces (one for each cause).
708     ASSERT_MATCH(
709         result,
710         R"((^|\s)allocated by thread .*?\n.*#00 pc(.|\n)*?(^|\s)allocated by thread .*?\n.*#00 pc)");
711   }
712 #else
713   GTEST_SKIP() << "Requires aarch64";
714 #endif
715 }
716 
717 #if defined(__aarch64__)
CreateTagMapping()718 static uintptr_t CreateTagMapping() {
719   // Some of the MTE tag dump tests assert that there is an inaccessible page to the left and right
720   // of the PROT_MTE page, so map three pages and set the two guard pages to PROT_NONE.
721   size_t page_size = getpagesize();
722   void* mapping = mmap(nullptr, page_size * 3, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
723   uintptr_t mapping_uptr = reinterpret_cast<uintptr_t>(mapping);
724   if (mapping == MAP_FAILED) {
725     return 0;
726   }
727   mprotect(reinterpret_cast<void*>(mapping_uptr + page_size), page_size,
728            PROT_READ | PROT_WRITE | PROT_MTE);
729   // Stripe the mapping, where even granules get tag '1', and odd granules get tag '0'.
730   for (uintptr_t offset = 0; offset < page_size; offset += 2 * kTagGranuleSize) {
731     uintptr_t tagged_addr = mapping_uptr + page_size + offset + (1ULL << 56);
732     __asm__ __volatile__(".arch_extension mte; stg %0, [%0]" : : "r"(tagged_addr) : "memory");
733   }
734   return mapping_uptr + page_size;
735 }
736 #endif
737 
TEST_F(CrasherTest,mte_register_tag_dump)738 TEST_F(CrasherTest, mte_register_tag_dump) {
739 #if defined(__aarch64__)
740   if (!mte_supported()) {
741     GTEST_SKIP() << "Requires MTE";
742   }
743 
744   int intercept_result;
745   unique_fd output_fd;
746   StartProcess([&]() {
747     SetTagCheckingLevelSync();
748     Trap(reinterpret_cast<void *>(CreateTagMapping()));
749   });
750 
751   StartIntercept(&output_fd);
752   FinishCrasher();
753   AssertDeath(SIGSEGV);
754   FinishIntercept(&intercept_result);
755 
756   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
757 
758   std::string result;
759   ConsumeFd(std::move(output_fd), &result);
760 
761   ASSERT_MATCH(result, R"(memory near x0:
762 .*
763 .*
764     01.............0 0000000000000000 0000000000000000  ................
765     00.............0)");
766 #else
767   GTEST_SKIP() << "Requires aarch64";
768 #endif
769 }
770 
TEST_F(CrasherTest,mte_fault_tag_dump_front_truncated)771 TEST_F(CrasherTest, mte_fault_tag_dump_front_truncated) {
772 #if defined(__aarch64__)
773   if (!mte_supported()) {
774     GTEST_SKIP() << "Requires MTE";
775   }
776 
777   int intercept_result;
778   unique_fd output_fd;
779   StartProcess([&]() {
780     SetTagCheckingLevelSync();
781     volatile char* p = reinterpret_cast<char*>(CreateTagMapping());
782     p[0] = 0;  // Untagged pointer, tagged memory.
783   });
784 
785   StartIntercept(&output_fd);
786   FinishCrasher();
787   AssertDeath(SIGSEGV);
788   FinishIntercept(&intercept_result);
789 
790   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
791 
792   std::string result;
793   ConsumeFd(std::move(output_fd), &result);
794 
795   ASSERT_MATCH(result, R"(Memory tags around the fault address.*
796 \s*=>0x[0-9a-f]+000:\[1\] 0  1  0)");
797 #else
798   GTEST_SKIP() << "Requires aarch64";
799 #endif
800 }
801 
TEST_F(CrasherTest,mte_fault_tag_dump)802 TEST_F(CrasherTest, mte_fault_tag_dump) {
803 #if defined(__aarch64__)
804   if (!mte_supported()) {
805     GTEST_SKIP() << "Requires MTE";
806   }
807 
808   int intercept_result;
809   unique_fd output_fd;
810   StartProcess([&]() {
811     SetTagCheckingLevelSync();
812     volatile char* p = reinterpret_cast<char*>(CreateTagMapping());
813     p[320] = 0;  // Untagged pointer, tagged memory.
814   });
815 
816   StartIntercept(&output_fd);
817   FinishCrasher();
818   AssertDeath(SIGSEGV);
819   FinishIntercept(&intercept_result);
820 
821   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
822 
823   std::string result;
824   ConsumeFd(std::move(output_fd), &result);
825 
826   ASSERT_MATCH(result, R"(Memory tags around the fault address.*
827 \s*0x[0-9a-f]+: 1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0
828 \s*=>0x[0-9a-f]+: 1  0  1  0 \[1\] 0  1  0  1  0  1  0  1  0  1  0
829 \s*0x[0-9a-f]+: 1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0
830 )");
831 #else
832   GTEST_SKIP() << "Requires aarch64";
833 #endif
834 }
835 
TEST_F(CrasherTest,mte_fault_tag_dump_rear_truncated)836 TEST_F(CrasherTest, mte_fault_tag_dump_rear_truncated) {
837 #if defined(__aarch64__)
838   if (!mte_supported()) {
839     GTEST_SKIP() << "Requires MTE";
840   }
841 
842   int intercept_result;
843   unique_fd output_fd;
844   StartProcess([&]() {
845     SetTagCheckingLevelSync();
846     size_t page_size = getpagesize();
847     volatile char* p = reinterpret_cast<char*>(CreateTagMapping());
848     p[page_size - kTagGranuleSize * 2] = 0;  // Untagged pointer, tagged memory.
849   });
850 
851   StartIntercept(&output_fd);
852   FinishCrasher();
853   AssertDeath(SIGSEGV);
854   FinishIntercept(&intercept_result);
855 
856   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
857 
858   std::string result;
859   ConsumeFd(std::move(output_fd), &result);
860 
861   ASSERT_MATCH(result, R"(Memory tags around the fault address)");
862   ASSERT_MATCH(result,
863                R"(\s*0x[0-9a-f]+: 1  0  1  0  1  0  1  0  1  0  1  0  1  0  1  0
864 \s*=>0x[0-9a-f]+: 1  0  1  0  1  0  1  0  1  0  1  0  1  0 \[1\] 0
865 
866 )");  // Ensure truncation happened and there's a newline after the tag fault.
867 #else
868   GTEST_SKIP() << "Requires aarch64";
869 #endif
870 }
871 
TEST_F(CrasherTest,LD_PRELOAD)872 TEST_F(CrasherTest, LD_PRELOAD) {
873   int intercept_result;
874   unique_fd output_fd;
875   StartProcess([]() {
876     setenv("LD_PRELOAD", "nonexistent.so", 1);
877     *reinterpret_cast<volatile char*>(0xdead) = '1';
878   });
879 
880   StartIntercept(&output_fd);
881   FinishCrasher();
882   AssertDeath(SIGSEGV);
883   FinishIntercept(&intercept_result);
884 
885   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
886 
887   std::string result;
888   ConsumeFd(std::move(output_fd), &result);
889   ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+dead)");
890 }
891 
TEST_F(CrasherTest,abort)892 TEST_F(CrasherTest, abort) {
893   int intercept_result;
894   unique_fd output_fd;
895   StartProcess([]() {
896     abort();
897   });
898   StartIntercept(&output_fd);
899   FinishCrasher();
900   AssertDeath(SIGABRT);
901   FinishIntercept(&intercept_result);
902 
903   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
904 
905   std::string result;
906   ConsumeFd(std::move(output_fd), &result);
907   ASSERT_BACKTRACE_FRAME(result, "abort");
908 }
909 
TEST_F(CrasherTest,signal)910 TEST_F(CrasherTest, signal) {
911   int intercept_result;
912   unique_fd output_fd;
913   StartProcess([]() {
914     while (true) {
915       sleep(1);
916     }
917   });
918   StartIntercept(&output_fd);
919   FinishCrasher();
920   ASSERT_EQ(0, kill(crasher_pid, SIGSEGV));
921 
922   AssertDeath(SIGSEGV);
923   FinishIntercept(&intercept_result);
924 
925   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
926 
927   std::string result;
928   ConsumeFd(std::move(output_fd), &result);
929   ASSERT_MATCH(
930       result,
931       R"(signal 11 \(SIGSEGV\), code 0 \(SI_USER from pid \d+, uid \d+\), fault addr --------)");
932   ASSERT_MATCH(result, R"(backtrace:)");
933 }
934 
TEST_F(CrasherTest,abort_message)935 TEST_F(CrasherTest, abort_message) {
936   int intercept_result;
937   unique_fd output_fd;
938   StartProcess([]() {
939     // Arrived at experimentally;
940     // logd truncates at 4062.
941     // strlen("Abort message: ''") is 17.
942     // That's 4045, but we also want a NUL.
943     char buf[4045 + 1];
944     memset(buf, 'x', sizeof(buf));
945     buf[sizeof(buf) - 1] = '\0';
946     android_set_abort_message(buf);
947     abort();
948   });
949   StartIntercept(&output_fd);
950   FinishCrasher();
951   AssertDeath(SIGABRT);
952   FinishIntercept(&intercept_result);
953 
954   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
955 
956   std::string result;
957   ConsumeFd(std::move(output_fd), &result);
958   ASSERT_MATCH(result, R"(Abort message: 'x{4045}')");
959 }
960 
TEST_F(CrasherTest,abort_message_newline_trimmed)961 TEST_F(CrasherTest, abort_message_newline_trimmed) {
962   int intercept_result;
963   unique_fd output_fd;
964   StartProcess([]() {
965     android_set_abort_message("Message with a newline.\n");
966     abort();
967   });
968   StartIntercept(&output_fd);
969   FinishCrasher();
970   AssertDeath(SIGABRT);
971   FinishIntercept(&intercept_result);
972 
973   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
974 
975   std::string result;
976   ConsumeFd(std::move(output_fd), &result);
977   ASSERT_MATCH(result, R"(Abort message: 'Message with a newline.')");
978 }
979 
TEST_F(CrasherTest,abort_message_multiple_newlines_trimmed)980 TEST_F(CrasherTest, abort_message_multiple_newlines_trimmed) {
981   int intercept_result;
982   unique_fd output_fd;
983   StartProcess([]() {
984     android_set_abort_message("Message with multiple newlines.\n\n\n\n\n");
985     abort();
986   });
987   StartIntercept(&output_fd);
988   FinishCrasher();
989   AssertDeath(SIGABRT);
990   FinishIntercept(&intercept_result);
991 
992   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
993 
994   std::string result;
995   ConsumeFd(std::move(output_fd), &result);
996   ASSERT_MATCH(result, R"(Abort message: 'Message with multiple newlines.')");
997 }
998 
TEST_F(CrasherTest,abort_message_backtrace)999 TEST_F(CrasherTest, abort_message_backtrace) {
1000   int intercept_result;
1001   unique_fd output_fd;
1002   StartProcess([]() {
1003     android_set_abort_message("not actually aborting");
1004     raise(BIONIC_SIGNAL_DEBUGGER);
1005     exit(0);
1006   });
1007   StartIntercept(&output_fd);
1008   FinishCrasher();
1009   AssertDeath(0);
1010   FinishIntercept(&intercept_result);
1011 
1012   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1013 
1014   std::string result;
1015   ConsumeFd(std::move(output_fd), &result);
1016   ASSERT_NOT_MATCH(result, R"(Abort message:)");
1017 }
1018 
TEST_F(CrasherTest,intercept_timeout)1019 TEST_F(CrasherTest, intercept_timeout) {
1020   int intercept_result;
1021   unique_fd output_fd;
1022   StartProcess([]() {
1023     abort();
1024   });
1025   StartIntercept(&output_fd);
1026 
1027   // Don't let crasher finish until we timeout.
1028   FinishIntercept(&intercept_result);
1029 
1030   ASSERT_NE(1, intercept_result) << "tombstoned reported success? (intercept_result = "
1031                                  << intercept_result << ")";
1032 
1033   FinishCrasher();
1034   AssertDeath(SIGABRT);
1035 }
1036 
TEST_F(CrasherTest,wait_for_debugger)1037 TEST_F(CrasherTest, wait_for_debugger) {
1038   if (!android::base::SetProperty(kWaitForDebuggerKey, "1")) {
1039     FAIL() << "failed to enable wait_for_debugger";
1040   }
1041   sleep(1);
1042 
1043   StartProcess([]() {
1044     abort();
1045   });
1046   FinishCrasher();
1047 
1048   int status;
1049   ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, WUNTRACED)));
1050   ASSERT_TRUE(WIFSTOPPED(status));
1051   ASSERT_EQ(SIGSTOP, WSTOPSIG(status));
1052 
1053   ASSERT_EQ(0, kill(crasher_pid, SIGCONT));
1054 
1055   AssertDeath(SIGABRT);
1056 }
1057 
TEST_F(CrasherTest,backtrace)1058 TEST_F(CrasherTest, backtrace) {
1059   std::string result;
1060   int intercept_result;
1061   unique_fd output_fd;
1062 
1063   StartProcess([]() {
1064     abort();
1065   });
1066   StartIntercept(&output_fd, kDebuggerdNativeBacktrace);
1067 
1068   std::this_thread::sleep_for(500ms);
1069 
1070   sigval val;
1071   val.sival_int = 1;
1072   ASSERT_EQ(0, sigqueue(crasher_pid, BIONIC_SIGNAL_DEBUGGER, val)) << strerror(errno);
1073   FinishIntercept(&intercept_result);
1074   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1075   ConsumeFd(std::move(output_fd), &result);
1076   ASSERT_BACKTRACE_FRAME(result, "read");
1077 
1078   int status;
1079   ASSERT_EQ(0, waitpid(crasher_pid, &status, WNOHANG | WUNTRACED));
1080 
1081   StartIntercept(&output_fd);
1082   FinishCrasher();
1083   AssertDeath(SIGABRT);
1084   FinishIntercept(&intercept_result);
1085   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1086   ConsumeFd(std::move(output_fd), &result);
1087   ASSERT_BACKTRACE_FRAME(result, "abort");
1088 }
1089 
TEST_F(CrasherTest,PR_SET_DUMPABLE_0_crash)1090 TEST_F(CrasherTest, PR_SET_DUMPABLE_0_crash) {
1091   int intercept_result;
1092   unique_fd output_fd;
1093   StartProcess([]() {
1094     prctl(PR_SET_DUMPABLE, 0);
1095     abort();
1096   });
1097 
1098   StartIntercept(&output_fd);
1099   FinishCrasher();
1100   AssertDeath(SIGABRT);
1101   FinishIntercept(&intercept_result);
1102 
1103   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1104 
1105   std::string result;
1106   ConsumeFd(std::move(output_fd), &result);
1107   ASSERT_BACKTRACE_FRAME(result, "abort");
1108 }
1109 
TEST_F(CrasherTest,capabilities)1110 TEST_F(CrasherTest, capabilities) {
1111   ASSERT_EQ(0U, getuid()) << "capability test requires root";
1112 
1113   StartProcess([]() {
1114     if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
1115       err(1, "failed to set PR_SET_KEEPCAPS");
1116     }
1117 
1118     if (setresuid(1, 1, 1) != 0) {
1119       err(1, "setresuid failed");
1120     }
1121 
1122     __user_cap_header_struct capheader;
1123     __user_cap_data_struct capdata[2];
1124     memset(&capheader, 0, sizeof(capheader));
1125     memset(&capdata, 0, sizeof(capdata));
1126 
1127     capheader.version = _LINUX_CAPABILITY_VERSION_3;
1128     capheader.pid = 0;
1129 
1130     // Turn on every third capability.
1131     static_assert(CAP_LAST_CAP > 33, "CAP_LAST_CAP <= 32");
1132     for (int i = 0; i < CAP_LAST_CAP; i += 3) {
1133       capdata[CAP_TO_INDEX(i)].permitted |= CAP_TO_MASK(i);
1134       capdata[CAP_TO_INDEX(i)].effective |= CAP_TO_MASK(i);
1135     }
1136 
1137     // Make sure CAP_SYS_PTRACE is off.
1138     capdata[CAP_TO_INDEX(CAP_SYS_PTRACE)].permitted &= ~(CAP_TO_MASK(CAP_SYS_PTRACE));
1139     capdata[CAP_TO_INDEX(CAP_SYS_PTRACE)].effective &= ~(CAP_TO_MASK(CAP_SYS_PTRACE));
1140 
1141     if (capset(&capheader, &capdata[0]) != 0) {
1142       err(1, "capset failed");
1143     }
1144 
1145     if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0) != 0) {
1146       err(1, "failed to drop ambient capabilities");
1147     }
1148 
1149     pthread_setname_np(pthread_self(), "thread_name");
1150     raise(SIGSYS);
1151   });
1152 
1153   unique_fd output_fd;
1154   StartIntercept(&output_fd);
1155   FinishCrasher();
1156   AssertDeath(SIGSYS);
1157 
1158   std::string result;
1159   int intercept_result;
1160   FinishIntercept(&intercept_result);
1161   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1162   ConsumeFd(std::move(output_fd), &result);
1163   ASSERT_MATCH(result, R"(name: thread_name\s+>>> .+debuggerd_test(32|64) <<<)");
1164   ASSERT_BACKTRACE_FRAME(result, "tgkill");
1165 }
1166 
TEST_F(CrasherTest,fake_pid)1167 TEST_F(CrasherTest, fake_pid) {
1168   int intercept_result;
1169   unique_fd output_fd;
1170 
1171   // Prime the getpid/gettid caches.
1172   UNUSED(getpid());
1173   UNUSED(gettid());
1174 
1175   std::function<pid_t()> clone_fn = []() {
1176     return syscall(__NR_clone, SIGCHLD, nullptr, nullptr, nullptr, nullptr);
1177   };
1178   StartProcess(
1179       []() {
1180         ASSERT_NE(getpid(), syscall(__NR_getpid));
1181         ASSERT_NE(gettid(), syscall(__NR_gettid));
1182         raise(SIGSEGV);
1183       },
1184       clone_fn);
1185 
1186   StartIntercept(&output_fd);
1187   FinishCrasher();
1188   AssertDeath(SIGSEGV);
1189   FinishIntercept(&intercept_result);
1190 
1191   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1192 
1193   std::string result;
1194   ConsumeFd(std::move(output_fd), &result);
1195   ASSERT_BACKTRACE_FRAME(result, "tgkill");
1196 }
1197 
1198 static const char* const kDebuggerdSeccompPolicy =
1199     "/system/etc/seccomp_policy/crash_dump." ABI_STRING ".policy";
1200 
setup_jail(minijail * jail)1201 static void setup_jail(minijail* jail) {
1202   if (!jail) {
1203     LOG(FATAL) << "failed to create minijail";
1204   }
1205 
1206   std::string policy;
1207   if (!android::base::ReadFileToString(kDebuggerdSeccompPolicy, &policy)) {
1208     PLOG(FATAL) << "failed to read policy file";
1209   }
1210 
1211   // Allow a bunch of syscalls used by the tests.
1212   policy += "\nclone: 1";
1213   policy += "\nsigaltstack: 1";
1214   policy += "\nnanosleep: 1";
1215   policy += "\ngetrlimit: 1";
1216   policy += "\nugetrlimit: 1";
1217 
1218   FILE* tmp_file = tmpfile();
1219   if (!tmp_file) {
1220     PLOG(FATAL) << "tmpfile failed";
1221   }
1222 
1223   unique_fd tmp_fd(TEMP_FAILURE_RETRY(dup(fileno(tmp_file))));
1224   if (!android::base::WriteStringToFd(policy, tmp_fd.get())) {
1225     PLOG(FATAL) << "failed to write policy to tmpfile";
1226   }
1227 
1228   if (lseek(tmp_fd.get(), 0, SEEK_SET) != 0) {
1229     PLOG(FATAL) << "failed to seek tmp_fd";
1230   }
1231 
1232   minijail_no_new_privs(jail);
1233   minijail_log_seccomp_filter_failures(jail);
1234   minijail_use_seccomp_filter(jail);
1235   minijail_parse_seccomp_filters_from_fd(jail, tmp_fd.release());
1236 }
1237 
seccomp_fork_impl(void (* prejail)())1238 static pid_t seccomp_fork_impl(void (*prejail)()) {
1239   ScopedMinijail jail{minijail_new()};
1240   setup_jail(jail.get());
1241 
1242   pid_t result = fork();
1243   if (result == -1) {
1244     return result;
1245   } else if (result != 0) {
1246     return result;
1247   }
1248 
1249   // Spawn and detach a thread that spins forever.
1250   std::atomic<bool> thread_ready(false);
1251   std::thread thread([&jail, &thread_ready]() {
1252     minijail_enter(jail.get());
1253     thread_ready = true;
1254     for (;;)
1255       ;
1256   });
1257   thread.detach();
1258 
1259   while (!thread_ready) {
1260     continue;
1261   }
1262 
1263   if (prejail) {
1264     prejail();
1265   }
1266 
1267   minijail_enter(jail.get());
1268   return result;
1269 }
1270 
seccomp_fork()1271 static pid_t seccomp_fork() {
1272   return seccomp_fork_impl(nullptr);
1273 }
1274 
TEST_F(CrasherTest,seccomp_crash)1275 TEST_F(CrasherTest, seccomp_crash) {
1276   int intercept_result;
1277   unique_fd output_fd;
1278 
1279   StartProcess([]() { abort(); }, &seccomp_fork);
1280 
1281   StartIntercept(&output_fd);
1282   FinishCrasher();
1283   AssertDeath(SIGABRT);
1284   FinishIntercept(&intercept_result);
1285   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1286 
1287   std::string result;
1288   ConsumeFd(std::move(output_fd), &result);
1289   ASSERT_BACKTRACE_FRAME(result, "abort");
1290 }
1291 
seccomp_fork_rlimit()1292 static pid_t seccomp_fork_rlimit() {
1293   return seccomp_fork_impl([]() {
1294     struct rlimit rlim = {
1295         .rlim_cur = 512 * 1024 * 1024,
1296         .rlim_max = 512 * 1024 * 1024,
1297     };
1298 
1299     if (setrlimit(RLIMIT_AS, &rlim) != 0) {
1300       raise(SIGINT);
1301     }
1302   });
1303 }
1304 
TEST_F(CrasherTest,seccomp_crash_oom)1305 TEST_F(CrasherTest, seccomp_crash_oom) {
1306   int intercept_result;
1307   unique_fd output_fd;
1308 
1309   StartProcess(
1310       []() {
1311         std::vector<void*> vec;
1312         for (int i = 0; i < 512; ++i) {
1313           char* buf = static_cast<char*>(malloc(1024 * 1024));
1314           if (!buf) {
1315             abort();
1316           }
1317           memset(buf, 0xff, 1024 * 1024);
1318           vec.push_back(buf);
1319         }
1320       },
1321       &seccomp_fork_rlimit);
1322 
1323   StartIntercept(&output_fd);
1324   FinishCrasher();
1325   AssertDeath(SIGABRT);
1326   FinishIntercept(&intercept_result);
1327   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1328 
1329   // We can't actually generate a backtrace, just make sure that the process terminates.
1330 }
1331 
raise_debugger_signal(DebuggerdDumpType dump_type)1332 __attribute__((__noinline__)) extern "C" bool raise_debugger_signal(DebuggerdDumpType dump_type) {
1333   siginfo_t siginfo;
1334   siginfo.si_code = SI_QUEUE;
1335   siginfo.si_pid = getpid();
1336   siginfo.si_uid = getuid();
1337 
1338   if (dump_type != kDebuggerdNativeBacktrace && dump_type != kDebuggerdTombstone) {
1339     PLOG(FATAL) << "invalid dump type";
1340   }
1341 
1342   siginfo.si_value.sival_int = dump_type == kDebuggerdNativeBacktrace;
1343 
1344   if (syscall(__NR_rt_tgsigqueueinfo, getpid(), gettid(), BIONIC_SIGNAL_DEBUGGER, &siginfo) != 0) {
1345     PLOG(ERROR) << "libdebuggerd_client: failed to send signal to self";
1346     return false;
1347   }
1348 
1349   return true;
1350 }
1351 
foo()1352 extern "C" void foo() {
1353   LOG(INFO) << "foo";
1354   std::this_thread::sleep_for(1s);
1355 }
1356 
bar()1357 extern "C" void bar() {
1358   LOG(INFO) << "bar";
1359   std::this_thread::sleep_for(1s);
1360 }
1361 
TEST_F(CrasherTest,seccomp_tombstone)1362 TEST_F(CrasherTest, seccomp_tombstone) {
1363   int intercept_result;
1364   unique_fd output_fd;
1365 
1366   static const auto dump_type = kDebuggerdTombstone;
1367   StartProcess(
1368       []() {
1369         std::thread a(foo);
1370         std::thread b(bar);
1371 
1372         std::this_thread::sleep_for(100ms);
1373 
1374         raise_debugger_signal(dump_type);
1375         _exit(0);
1376       },
1377       &seccomp_fork);
1378 
1379   StartIntercept(&output_fd, dump_type);
1380   FinishCrasher();
1381   AssertDeath(0);
1382   FinishIntercept(&intercept_result);
1383   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1384 
1385   std::string result;
1386   ConsumeFd(std::move(output_fd), &result);
1387   ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
1388   ASSERT_BACKTRACE_FRAME(result, "foo");
1389   ASSERT_BACKTRACE_FRAME(result, "bar");
1390 }
1391 
TEST_F(CrasherTest,seccomp_tombstone_thread_abort)1392 TEST_F(CrasherTest, seccomp_tombstone_thread_abort) {
1393   int intercept_result;
1394   unique_fd output_fd;
1395 
1396   static const auto dump_type = kDebuggerdTombstone;
1397   StartProcess(
1398       []() {
1399         std::thread abort_thread([] { abort(); });
1400         abort_thread.join();
1401       },
1402       &seccomp_fork);
1403 
1404   StartIntercept(&output_fd, dump_type);
1405   FinishCrasher();
1406   AssertDeath(SIGABRT);
1407   FinishIntercept(&intercept_result);
1408   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1409 
1410   std::string result;
1411   ConsumeFd(std::move(output_fd), &result);
1412   ASSERT_BACKTRACE_FRAME(result, "abort");
1413 }
1414 
TEST_F(CrasherTest,seccomp_tombstone_multiple_threads_abort)1415 TEST_F(CrasherTest, seccomp_tombstone_multiple_threads_abort) {
1416   int intercept_result;
1417   unique_fd output_fd;
1418 
1419   static const auto dump_type = kDebuggerdTombstone;
1420   StartProcess(
1421       []() {
1422         std::thread a(foo);
1423         std::thread b(bar);
1424 
1425         std::this_thread::sleep_for(100ms);
1426 
1427         std::thread abort_thread([] { abort(); });
1428         abort_thread.join();
1429       },
1430       &seccomp_fork);
1431 
1432   StartIntercept(&output_fd, dump_type);
1433   FinishCrasher();
1434   AssertDeath(SIGABRT);
1435   FinishIntercept(&intercept_result);
1436   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1437 
1438   std::string result;
1439   ConsumeFd(std::move(output_fd), &result);
1440   ASSERT_BACKTRACE_FRAME(result, "abort");
1441   ASSERT_BACKTRACE_FRAME(result, "foo");
1442   ASSERT_BACKTRACE_FRAME(result, "bar");
1443   ASSERT_BACKTRACE_FRAME(result, "main");
1444 }
1445 
TEST_F(CrasherTest,seccomp_backtrace)1446 TEST_F(CrasherTest, seccomp_backtrace) {
1447   int intercept_result;
1448   unique_fd output_fd;
1449 
1450   static const auto dump_type = kDebuggerdNativeBacktrace;
1451   StartProcess(
1452       []() {
1453         std::thread a(foo);
1454         std::thread b(bar);
1455 
1456         std::this_thread::sleep_for(100ms);
1457 
1458         raise_debugger_signal(dump_type);
1459         _exit(0);
1460       },
1461       &seccomp_fork);
1462 
1463   StartIntercept(&output_fd, dump_type);
1464   FinishCrasher();
1465   AssertDeath(0);
1466   FinishIntercept(&intercept_result);
1467   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1468 
1469   std::string result;
1470   ConsumeFd(std::move(output_fd), &result);
1471   ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
1472   ASSERT_BACKTRACE_FRAME(result, "foo");
1473   ASSERT_BACKTRACE_FRAME(result, "bar");
1474 }
1475 
TEST_F(CrasherTest,seccomp_backtrace_from_thread)1476 TEST_F(CrasherTest, seccomp_backtrace_from_thread) {
1477   int intercept_result;
1478   unique_fd output_fd;
1479 
1480   static const auto dump_type = kDebuggerdNativeBacktrace;
1481   StartProcess(
1482       []() {
1483         std::thread a(foo);
1484         std::thread b(bar);
1485 
1486         std::this_thread::sleep_for(100ms);
1487 
1488         std::thread raise_thread([] {
1489           raise_debugger_signal(dump_type);
1490           _exit(0);
1491         });
1492         raise_thread.join();
1493       },
1494       &seccomp_fork);
1495 
1496   StartIntercept(&output_fd, dump_type);
1497   FinishCrasher();
1498   AssertDeath(0);
1499   FinishIntercept(&intercept_result);
1500   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1501 
1502   std::string result;
1503   ConsumeFd(std::move(output_fd), &result);
1504   ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
1505   ASSERT_BACKTRACE_FRAME(result, "foo");
1506   ASSERT_BACKTRACE_FRAME(result, "bar");
1507   ASSERT_BACKTRACE_FRAME(result, "main");
1508 }
1509 
TEST_F(CrasherTest,seccomp_crash_logcat)1510 TEST_F(CrasherTest, seccomp_crash_logcat) {
1511   StartProcess([]() { abort(); }, &seccomp_fork);
1512   FinishCrasher();
1513 
1514   // Make sure we don't get SIGSYS when trying to dump a crash to logcat.
1515   AssertDeath(SIGABRT);
1516 }
1517 
TEST_F(CrasherTest,competing_tracer)1518 TEST_F(CrasherTest, competing_tracer) {
1519   int intercept_result;
1520   unique_fd output_fd;
1521   StartProcess([]() {
1522     raise(SIGABRT);
1523   });
1524 
1525   StartIntercept(&output_fd);
1526 
1527   ASSERT_EQ(0, ptrace(PTRACE_SEIZE, crasher_pid, 0, 0));
1528   FinishCrasher();
1529 
1530   int status;
1531   ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
1532   ASSERT_TRUE(WIFSTOPPED(status));
1533   ASSERT_EQ(SIGABRT, WSTOPSIG(status));
1534 
1535   ASSERT_EQ(0, ptrace(PTRACE_CONT, crasher_pid, 0, SIGABRT));
1536   FinishIntercept(&intercept_result);
1537   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1538 
1539   std::string result;
1540   ConsumeFd(std::move(output_fd), &result);
1541   std::string regex = R"(failed to attach to thread \d+, already traced by )";
1542   regex += std::to_string(gettid());
1543   regex += R"( \(.+debuggerd_test)";
1544   ASSERT_MATCH(result, regex.c_str());
1545 
1546   ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
1547   ASSERT_TRUE(WIFSTOPPED(status));
1548   ASSERT_EQ(SIGABRT, WSTOPSIG(status));
1549 
1550   ASSERT_EQ(0, ptrace(PTRACE_DETACH, crasher_pid, 0, SIGABRT));
1551   AssertDeath(SIGABRT);
1552 }
1553 
1554 struct GwpAsanTestParameters {
1555   size_t alloc_size;
1556   bool free_before_access;
1557   int access_offset;
1558   std::string cause_needle;  // Needle to be found in the "Cause: [GWP-ASan]" line.
1559 };
1560 
1561 struct GwpAsanCrasherTest
1562     : CrasherTest,
1563       testing::WithParamInterface<
1564           std::tuple<GwpAsanTestParameters, /* recoverable */ bool, /* seccomp */ bool>> {};
1565 
1566 GwpAsanTestParameters gwp_asan_tests[] = {
1567     {/* alloc_size */ 7, /* free_before_access */ true, /* access_offset */ 0,
1568      "Use After Free, 0 bytes into a 7-byte allocation"},
1569     {/* alloc_size */ 15, /* free_before_access */ true, /* access_offset */ 1,
1570      "Use After Free, 1 byte into a 15-byte allocation"},
1571     {/* alloc_size */ 4096, /* free_before_access */ false, /* access_offset */ 4098,
1572      "Buffer Overflow, 2 bytes right of a 4096-byte allocation"},
1573     {/* alloc_size */ 4096, /* free_before_access */ false, /* access_offset */ -1,
1574      "Buffer Underflow, 1 byte left of a 4096-byte allocation"},
1575 };
1576 
1577 INSTANTIATE_TEST_SUITE_P(
1578     GwpAsanTests, GwpAsanCrasherTest,
1579     testing::Combine(testing::ValuesIn(gwp_asan_tests),
1580                      /* recoverable */ testing::Bool(),
1581                      /* seccomp */ testing::Bool()),
1582     [](const testing::TestParamInfo<
__anond0b6624a2a02(const testing::TestParamInfo< std::tuple<GwpAsanTestParameters, bool, bool>>& info) 1583         std::tuple<GwpAsanTestParameters, /* recoverable */ bool, /* seccomp */ bool>>& info) {
1584       const GwpAsanTestParameters& params = std::get<0>(info.param);
1585       std::string name = params.free_before_access ? "UseAfterFree" : "Overflow";
1586       name += testing::PrintToString(params.alloc_size);
1587       name += "Alloc";
1588       if (params.access_offset < 0) {
1589         name += "Left";
1590         name += testing::PrintToString(params.access_offset * -1);
1591       } else {
1592         name += "Right";
1593         name += testing::PrintToString(params.access_offset);
1594       }
1595       name += "Bytes";
1596       if (std::get<1>(info.param)) name += "Recoverable";
1597       if (std::get<2>(info.param)) name += "Seccomp";
1598       return name;
1599     });
1600 
TEST_P(GwpAsanCrasherTest,run_gwp_asan_test)1601 TEST_P(GwpAsanCrasherTest, run_gwp_asan_test) {
1602   if (mte_supported()) {
1603     // Skip this test on MTE hardware, as MTE will reliably catch these errors
1604     // instead of GWP-ASan.
1605     GTEST_SKIP() << "Skipped on MTE.";
1606   }
1607   // Skip this test on HWASan, which will reliably catch test errors as well.
1608   SKIP_WITH_HWASAN;
1609 
1610   GwpAsanTestParameters params = std::get<0>(GetParam());
1611   bool recoverable = std::get<1>(GetParam());
1612   LogcatCollector logcat_collector;
1613 
1614   int intercept_result;
1615   unique_fd output_fd;
1616   StartProcess([&recoverable]() {
1617     const char* env[] = {"GWP_ASAN_SAMPLE_RATE=1", "GWP_ASAN_PROCESS_SAMPLING=1",
1618                          "GWP_ASAN_MAX_ALLOCS=40000", nullptr, nullptr};
1619     if (recoverable) {
1620       env[3] = "GWP_ASAN_RECOVERABLE=true";
1621     }
1622     std::string test_name = ::testing::UnitTest::GetInstance()->current_test_info()->name();
1623     test_name = std::regex_replace(test_name, std::regex("run_gwp_asan_test"),
1624                                    "DISABLED_run_gwp_asan_test");
1625     std::string test_filter = "--gtest_filter=*";
1626     test_filter += test_name;
1627     std::string this_binary = android::base::GetExecutablePath();
1628     const char* args[] = {this_binary.c_str(), "--gtest_also_run_disabled_tests",
1629                           test_filter.c_str(), nullptr};
1630     // We check the crash report from a debuggerd handler and from logcat. The
1631     // echo from stdout/stderr of the subprocess trips up atest, because it
1632     // doesn't like that two tests started in a row without the first one
1633     // finishing (even though the second one is in a subprocess).
1634     close(STDOUT_FILENO);
1635     close(STDERR_FILENO);
1636     execve(this_binary.c_str(), const_cast<char**>(args), const_cast<char**>(env));
1637   });
1638 
1639   StartIntercept(&output_fd);
1640   FinishCrasher();
1641   if (recoverable) {
1642     AssertDeath(0);
1643   } else {
1644     AssertDeath(SIGSEGV);
1645   }
1646   FinishIntercept(&intercept_result);
1647 
1648   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1649 
1650   std::vector<std::string> log_sources(2);
1651   ConsumeFd(std::move(output_fd), &log_sources[0]);
1652   logcat_collector.Collect(&log_sources[1]);
1653 
1654   // seccomp forces the fallback handler, which doesn't print GWP-ASan debugging
1655   // information. Make sure the recovery still works, but the report won't be
1656   // hugely useful, it looks like a regular SEGV.
1657   bool seccomp = std::get<2>(GetParam());
1658   if (!seccomp) {
1659     for (const auto& result : log_sources) {
1660       ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\))");
1661       ASSERT_MATCH(result, R"(Cause: \[GWP-ASan\]: )" + params.cause_needle);
1662       if (params.free_before_access) {
1663         ASSERT_MATCH(result, R"(deallocated by thread .*\n.*#00 pc)");
1664       }
1665       ASSERT_MATCH(result, R"((^|\s)allocated by thread .*\n.*#00 pc)");
1666     }
1667   }
1668 }
1669 
TEST_P(GwpAsanCrasherTest,DISABLED_run_gwp_asan_test)1670 TEST_P(GwpAsanCrasherTest, DISABLED_run_gwp_asan_test) {
1671   GwpAsanTestParameters params = std::get<0>(GetParam());
1672   bool seccomp = std::get<2>(GetParam());
1673   if (seccomp) {
1674     ScopedMinijail jail{minijail_new()};
1675     setup_jail(jail.get());
1676     minijail_enter(jail.get());
1677   }
1678 
1679   // Use 'volatile' to prevent a very clever compiler eliminating the store.
1680   char* volatile p = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1681   if (params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
1682   p[params.access_offset] = 42;
1683   if (!params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
1684 
1685   bool recoverable = std::get<1>(GetParam());
1686   ASSERT_TRUE(recoverable);  // Non-recoverable should have crashed.
1687 
1688   // As we're in recoverable mode, trigger another 2x use-after-frees (ensuring
1689   // we end with at least one in a different slot), make sure the process still
1690   // doesn't crash.
1691   p = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1692   char* volatile p2 = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1693   free(static_cast<void*>(const_cast<char*>(p)));
1694   free(static_cast<void*>(const_cast<char*>(p2)));
1695   *p = 42;
1696   *p2 = 42;
1697 
1698   // Under clang coverage (which is a default TEST_MAPPING presubmit target), the
1699   // recoverable+seccomp tests fail because the minijail prevents some atexit syscalls that clang
1700   // coverage does. Thus, skip the atexit handlers.
1701   _exit(0);
1702 }
1703 
TEST_F(CrasherTest,fdsan_warning_abort_message)1704 TEST_F(CrasherTest, fdsan_warning_abort_message) {
1705   int intercept_result;
1706   unique_fd output_fd;
1707 
1708   StartProcess([]() {
1709     android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
1710     unique_fd fd(TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY | O_CLOEXEC)));
1711     if (fd == -1) {
1712       abort();
1713     }
1714     close(fd.get());
1715     _exit(0);
1716   });
1717 
1718   StartIntercept(&output_fd);
1719   FinishCrasher();
1720   AssertDeath(0);
1721   FinishIntercept(&intercept_result);
1722   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1723 
1724   std::string result;
1725   ConsumeFd(std::move(output_fd), &result);
1726   ASSERT_MATCH(result, "Abort message: 'attempted to close");
1727 }
1728 
TEST(crash_dump,zombie)1729 TEST(crash_dump, zombie) {
1730   pid_t forkpid = fork();
1731 
1732   pid_t rc;
1733   int status;
1734 
1735   if (forkpid == 0) {
1736     errno = 0;
1737     rc = waitpid(-1, &status, WNOHANG | __WALL | __WNOTHREAD);
1738     if (rc != -1 || errno != ECHILD) {
1739       errx(2, "first waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
1740     }
1741 
1742     raise(BIONIC_SIGNAL_DEBUGGER);
1743 
1744     errno = 0;
1745     rc = TEMP_FAILURE_RETRY(waitpid(-1, &status, __WALL | __WNOTHREAD));
1746     if (rc != -1 || errno != ECHILD) {
1747       errx(2, "second waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
1748     }
1749     _exit(0);
1750   } else {
1751     rc = TEMP_FAILURE_RETRY(waitpid(forkpid, &status, 0));
1752     ASSERT_EQ(forkpid, rc);
1753     ASSERT_TRUE(WIFEXITED(status));
1754     ASSERT_EQ(0, WEXITSTATUS(status));
1755   }
1756 }
1757 
TEST(tombstoned,no_notify)1758 TEST(tombstoned, no_notify) {
1759   // Do this a few times.
1760   for (int i = 0; i < 3; ++i) {
1761     pid_t pid = 123'456'789 + i;
1762 
1763     unique_fd intercept_fd, output_fd;
1764     InterceptStatus status;
1765     tombstoned_intercept(pid, &intercept_fd, &output_fd, &status, kDebuggerdTombstone);
1766     ASSERT_EQ(InterceptStatus::kRegistered, status);
1767 
1768     {
1769       unique_fd tombstoned_socket, input_fd;
1770       ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
1771       ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid)));
1772     }
1773 
1774     pid_t read_pid;
1775     ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid)));
1776     ASSERT_EQ(read_pid, pid);
1777   }
1778 }
1779 
TEST(tombstoned,stress)1780 TEST(tombstoned, stress) {
1781   // Spawn threads to simultaneously do a bunch of failing dumps and a bunch of successful dumps.
1782   static constexpr int kDumpCount = 100;
1783 
1784   std::atomic<bool> start(false);
1785   std::vector<std::thread> threads;
1786   threads.emplace_back([&start]() {
1787     while (!start) {
1788       continue;
1789     }
1790 
1791     // Use a way out of range pid, to avoid stomping on an actual process.
1792     pid_t pid_base = 1'000'000;
1793 
1794     for (int dump = 0; dump < kDumpCount; ++dump) {
1795       pid_t pid = pid_base + dump;
1796 
1797       unique_fd intercept_fd, output_fd;
1798       InterceptStatus status;
1799       tombstoned_intercept(pid, &intercept_fd, &output_fd, &status, kDebuggerdTombstone);
1800       ASSERT_EQ(InterceptStatus::kRegistered, status);
1801 
1802       // Pretend to crash, and then immediately close the socket.
1803       unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName,
1804                                            ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
1805       if (sockfd == -1) {
1806         FAIL() << "failed to connect to tombstoned: " << strerror(errno);
1807       }
1808       TombstonedCrashPacket packet = {};
1809       packet.packet_type = CrashPacketType::kDumpRequest;
1810       packet.packet.dump_request.pid = pid;
1811       if (TEMP_FAILURE_RETRY(write(sockfd, &packet, sizeof(packet))) != sizeof(packet)) {
1812         FAIL() << "failed to write to tombstoned: " << strerror(errno);
1813       }
1814 
1815       continue;
1816     }
1817   });
1818 
1819   threads.emplace_back([&start]() {
1820     while (!start) {
1821       continue;
1822     }
1823 
1824     // Use a way out of range pid, to avoid stomping on an actual process.
1825     pid_t pid_base = 2'000'000;
1826 
1827     for (int dump = 0; dump < kDumpCount; ++dump) {
1828       pid_t pid = pid_base + dump;
1829 
1830       unique_fd intercept_fd, output_fd;
1831       InterceptStatus status;
1832       tombstoned_intercept(pid, &intercept_fd, &output_fd, &status, kDebuggerdTombstone);
1833       ASSERT_EQ(InterceptStatus::kRegistered, status);
1834 
1835       {
1836         unique_fd tombstoned_socket, input_fd;
1837         ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
1838         ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid)));
1839         tombstoned_notify_completion(tombstoned_socket.get());
1840       }
1841 
1842       // TODO: Fix the race that requires this sleep.
1843       std::this_thread::sleep_for(50ms);
1844 
1845       pid_t read_pid;
1846       ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid)));
1847       ASSERT_EQ(read_pid, pid);
1848     }
1849   });
1850 
1851   start = true;
1852 
1853   for (std::thread& thread : threads) {
1854     thread.join();
1855   }
1856 }
1857 
TEST(tombstoned,java_trace_intercept_smoke)1858 TEST(tombstoned, java_trace_intercept_smoke) {
1859   // Using a "real" PID is a little dangerous here - if the test fails
1860   // or crashes, we might end up getting a bogus / unreliable stack
1861   // trace.
1862   const pid_t self = getpid();
1863 
1864   unique_fd intercept_fd, output_fd;
1865   InterceptStatus status;
1866   tombstoned_intercept(self, &intercept_fd, &output_fd, &status, kDebuggerdJavaBacktrace);
1867   ASSERT_EQ(InterceptStatus::kRegistered, status);
1868 
1869   // First connect to tombstoned requesting a native tombstone. This
1870   // should result in a "regular" FD and not the installed intercept.
1871   const char native[] = "native";
1872   unique_fd tombstoned_socket, input_fd;
1873   ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
1874   ASSERT_TRUE(android::base::WriteFully(input_fd.get(), native, sizeof(native)));
1875   tombstoned_notify_completion(tombstoned_socket.get());
1876 
1877   // Then, connect to tombstoned asking for a java backtrace. This *should*
1878   // trigger the intercept.
1879   const char java[] = "java";
1880   ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdJavaBacktrace));
1881   ASSERT_TRUE(android::base::WriteFully(input_fd.get(), java, sizeof(java)));
1882   tombstoned_notify_completion(tombstoned_socket.get());
1883 
1884   char outbuf[sizeof(java)];
1885   ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
1886   ASSERT_STREQ("java", outbuf);
1887 }
1888 
TEST(tombstoned,multiple_intercepts)1889 TEST(tombstoned, multiple_intercepts) {
1890   const pid_t fake_pid = 1'234'567;
1891   unique_fd intercept_fd, output_fd;
1892   InterceptStatus status;
1893   tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &status, kDebuggerdJavaBacktrace);
1894   ASSERT_EQ(InterceptStatus::kRegistered, status);
1895 
1896   unique_fd intercept_fd_2, output_fd_2;
1897   tombstoned_intercept(fake_pid, &intercept_fd_2, &output_fd_2, &status, kDebuggerdNativeBacktrace);
1898   ASSERT_EQ(InterceptStatus::kFailedAlreadyRegistered, status);
1899 }
1900 
TEST(tombstoned,intercept_any)1901 TEST(tombstoned, intercept_any) {
1902   const pid_t fake_pid = 1'234'567;
1903 
1904   unique_fd intercept_fd, output_fd;
1905   InterceptStatus status;
1906   tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &status, kDebuggerdNativeBacktrace);
1907   ASSERT_EQ(InterceptStatus::kRegistered, status);
1908 
1909   const char any[] = "any";
1910   unique_fd tombstoned_socket, input_fd;
1911   ASSERT_TRUE(tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdAnyIntercept));
1912   ASSERT_TRUE(android::base::WriteFully(input_fd.get(), any, sizeof(any)));
1913   tombstoned_notify_completion(tombstoned_socket.get());
1914 
1915   char outbuf[sizeof(any)];
1916   ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
1917   ASSERT_STREQ("any", outbuf);
1918 }
1919 
TEST(tombstoned,interceptless_backtrace)1920 TEST(tombstoned, interceptless_backtrace) {
1921   // Generate 50 backtraces, and then check to see that we haven't created 50 new tombstones.
1922   auto get_tombstone_timestamps = []() -> std::map<int, time_t> {
1923     std::map<int, time_t> result;
1924     for (int i = 0; i < 99; ++i) {
1925       std::string path = android::base::StringPrintf("/data/tombstones/tombstone_%02d", i);
1926       struct stat st;
1927       if (stat(path.c_str(), &st) == 0) {
1928         result[i] = st.st_mtim.tv_sec;
1929       }
1930     }
1931     return result;
1932   };
1933 
1934   auto before = get_tombstone_timestamps();
1935   for (int i = 0; i < 50; ++i) {
1936     raise_debugger_signal(kDebuggerdNativeBacktrace);
1937   }
1938   auto after = get_tombstone_timestamps();
1939 
1940   int diff = 0;
1941   for (int i = 0; i < 99; ++i) {
1942     if (after.count(i) == 0) {
1943       continue;
1944     }
1945     if (before.count(i) == 0) {
1946       ++diff;
1947       continue;
1948     }
1949     if (before[i] != after[i]) {
1950       ++diff;
1951     }
1952   }
1953 
1954   // We can't be sure that nothing's crash looping in the background.
1955   // This should be good enough, though...
1956   ASSERT_LT(diff, 10) << "too many new tombstones; is something crashing in the background?";
1957 }
1958 
overflow_stack(void * p)1959 static __attribute__((__noinline__)) void overflow_stack(void* p) {
1960   void* buf[1];
1961   buf[0] = p;
1962   static volatile void* global = buf;
1963   if (global) {
1964     global = buf;
1965     overflow_stack(&buf);
1966   }
1967 }
1968 
TEST_F(CrasherTest,stack_overflow)1969 TEST_F(CrasherTest, stack_overflow) {
1970   int intercept_result;
1971   unique_fd output_fd;
1972   StartProcess([]() { overflow_stack(nullptr); });
1973 
1974   StartIntercept(&output_fd);
1975   FinishCrasher();
1976   AssertDeath(SIGSEGV);
1977   FinishIntercept(&intercept_result);
1978 
1979   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1980 
1981   std::string result;
1982   ConsumeFd(std::move(output_fd), &result);
1983   ASSERT_MATCH(result, R"(Cause: stack pointer[^\n]*stack overflow.\n)");
1984 }
1985 
GetTestLibraryPath()1986 static std::string GetTestLibraryPath() {
1987   std::string test_lib(testing::internal::GetArgvs()[0]);
1988   auto const value = test_lib.find_last_of('/');
1989   if (value == std::string::npos) {
1990     test_lib = "./";
1991   } else {
1992     test_lib = test_lib.substr(0, value + 1) + "./";
1993   }
1994   return test_lib + "libcrash_test.so";
1995 }
1996 
CreateEmbeddedLibrary(int out_fd)1997 static void CreateEmbeddedLibrary(int out_fd) {
1998   std::string test_lib(GetTestLibraryPath());
1999   android::base::unique_fd fd(open(test_lib.c_str(), O_RDONLY | O_CLOEXEC));
2000   ASSERT_NE(fd.get(), -1);
2001   off_t file_size = lseek(fd, 0, SEEK_END);
2002   ASSERT_EQ(lseek(fd, 0, SEEK_SET), 0);
2003   std::vector<uint8_t> contents(file_size);
2004   ASSERT_TRUE(android::base::ReadFully(fd, contents.data(), contents.size()));
2005 
2006   // Put the shared library data at a pagesize() offset.
2007   ASSERT_EQ(lseek(out_fd, 4 * getpagesize(), SEEK_CUR), 4 * getpagesize());
2008   ASSERT_EQ(static_cast<size_t>(write(out_fd, contents.data(), contents.size())), contents.size());
2009 }
2010 
TEST_F(CrasherTest,non_zero_offset_in_library)2011 TEST_F(CrasherTest, non_zero_offset_in_library) {
2012   int intercept_result;
2013   unique_fd output_fd;
2014   TemporaryFile tf;
2015   CreateEmbeddedLibrary(tf.fd);
2016   StartProcess([&tf]() {
2017     android_dlextinfo extinfo{};
2018     extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
2019     extinfo.library_fd = tf.fd;
2020     extinfo.library_fd_offset = 4 * getpagesize();
2021     void* handle = android_dlopen_ext(tf.path, RTLD_NOW, &extinfo);
2022     if (handle == nullptr) {
2023       _exit(1);
2024     }
2025     void (*crash_func)() = reinterpret_cast<void (*)()>(dlsym(handle, "crash"));
2026     if (crash_func == nullptr) {
2027       _exit(1);
2028     }
2029     crash_func();
2030   });
2031 
2032   StartIntercept(&output_fd);
2033   FinishCrasher();
2034   AssertDeath(SIGSEGV);
2035   FinishIntercept(&intercept_result);
2036 
2037   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2038 
2039   std::string result;
2040   ConsumeFd(std::move(output_fd), &result);
2041 
2042   // Verify the crash includes an offset value in the backtrace.
2043   std::string match_str = android::base::StringPrintf("%s\\!libcrash_test.so \\(offset 0x%x\\)",
2044                                                       tf.path, 4 * getpagesize());
2045   ASSERT_MATCH(result, match_str);
2046 }
2047 
CopySharedLibrary(const char * tmp_dir,std::string * tmp_so_name)2048 static bool CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) {
2049   std::string test_lib(GetTestLibraryPath());
2050 
2051   *tmp_so_name = std::string(tmp_dir) + "/libcrash_test.so";
2052   std::string cp_cmd = android::base::StringPrintf("cp %s %s", test_lib.c_str(), tmp_dir);
2053 
2054   // Copy the shared so to a tempory directory.
2055   return system(cp_cmd.c_str()) == 0;
2056 }
2057 
TEST_F(CrasherTest,unreadable_elf)2058 TEST_F(CrasherTest, unreadable_elf) {
2059   int intercept_result;
2060   unique_fd output_fd;
2061   std::string tmp_so_name;
2062   StartProcess([&tmp_so_name]() {
2063     TemporaryDir td;
2064     if (!CopySharedLibrary(td.path, &tmp_so_name)) {
2065       _exit(1);
2066     }
2067     void* handle = dlopen(tmp_so_name.c_str(), RTLD_NOW);
2068     if (handle == nullptr) {
2069       _exit(1);
2070     }
2071     // Delete the original shared library so that we get the warning
2072     // about unreadable elf files.
2073     if (unlink(tmp_so_name.c_str()) == -1) {
2074       _exit(1);
2075     }
2076     void (*crash_func)() = reinterpret_cast<void (*)()>(dlsym(handle, "crash"));
2077     if (crash_func == nullptr) {
2078       _exit(1);
2079     }
2080     crash_func();
2081   });
2082 
2083   StartIntercept(&output_fd);
2084   FinishCrasher();
2085   AssertDeath(SIGSEGV);
2086   FinishIntercept(&intercept_result);
2087 
2088   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2089 
2090   std::string result;
2091   ConsumeFd(std::move(output_fd), &result);
2092   ASSERT_MATCH(result, R"(NOTE: Function names and BuildId information is missing )");
2093   std::string match_str = "NOTE:   " + tmp_so_name;
2094   ASSERT_MATCH(result, match_str);
2095 }
2096 
TEST(tombstoned,proto)2097 TEST(tombstoned, proto) {
2098   const pid_t self = getpid();
2099   unique_fd tombstoned_socket, text_fd, proto_fd;
2100   ASSERT_TRUE(
2101       tombstoned_connect(self, &tombstoned_socket, &text_fd, &proto_fd, kDebuggerdTombstoneProto));
2102 
2103   tombstoned_notify_completion(tombstoned_socket.get());
2104 
2105   ASSERT_NE(-1, text_fd.get());
2106   ASSERT_NE(-1, proto_fd.get());
2107 
2108   struct stat text_st;
2109   ASSERT_EQ(0, fstat(text_fd.get(), &text_st));
2110 
2111   // Give tombstoned some time to link the files into place.
2112   std::this_thread::sleep_for(100ms);
2113 
2114   // Find the tombstone.
2115   std::optional<std::string> tombstone_file;
2116   std::unique_ptr<DIR, decltype(&closedir)> dir_h(opendir("/data/tombstones"), closedir);
2117   ASSERT_TRUE(dir_h != nullptr);
2118   std::regex tombstone_re("tombstone_\\d+");
2119   dirent* entry;
2120   while ((entry = readdir(dir_h.get())) != nullptr) {
2121     if (!std::regex_match(entry->d_name, tombstone_re)) {
2122       continue;
2123     }
2124     std::string path = android::base::StringPrintf("/data/tombstones/%s", entry->d_name);
2125 
2126     struct stat st;
2127     if (TEMP_FAILURE_RETRY(stat(path.c_str(), &st)) != 0) {
2128       continue;
2129     }
2130 
2131     if (st.st_dev == text_st.st_dev && st.st_ino == text_st.st_ino) {
2132       tombstone_file = path;
2133       break;
2134     }
2135   }
2136 
2137   ASSERT_TRUE(tombstone_file);
2138   std::string proto_path = tombstone_file.value() + ".pb";
2139 
2140   struct stat proto_fd_st;
2141   struct stat proto_file_st;
2142   ASSERT_EQ(0, fstat(proto_fd.get(), &proto_fd_st));
2143   ASSERT_EQ(0, stat(proto_path.c_str(), &proto_file_st));
2144 
2145   ASSERT_EQ(proto_fd_st.st_dev, proto_file_st.st_dev);
2146   ASSERT_EQ(proto_fd_st.st_ino, proto_file_st.st_ino);
2147 }
2148 
TEST(tombstoned,proto_intercept)2149 TEST(tombstoned, proto_intercept) {
2150   const pid_t self = getpid();
2151   unique_fd intercept_fd, output_fd;
2152   InterceptStatus status;
2153 
2154   tombstoned_intercept(self, &intercept_fd, &output_fd, &status, kDebuggerdTombstone);
2155   ASSERT_EQ(InterceptStatus::kRegistered, status);
2156 
2157   unique_fd tombstoned_socket, text_fd, proto_fd;
2158   ASSERT_TRUE(
2159       tombstoned_connect(self, &tombstoned_socket, &text_fd, &proto_fd, kDebuggerdTombstoneProto));
2160   ASSERT_TRUE(android::base::WriteStringToFd("foo", text_fd.get()));
2161   tombstoned_notify_completion(tombstoned_socket.get());
2162 
2163   text_fd.reset();
2164 
2165   std::string output;
2166   ASSERT_TRUE(android::base::ReadFdToString(output_fd, &output));
2167   ASSERT_EQ("foo", output);
2168 }
2169 
2170 // Verify that when an intercept is present for the main thread, and the signal
2171 // is received on a different thread, the intercept still works.
TEST_F(CrasherTest,intercept_for_main_thread_signal_on_side_thread)2172 TEST_F(CrasherTest, intercept_for_main_thread_signal_on_side_thread) {
2173   StartProcess([]() {
2174     std::thread thread([]() {
2175       // Raise the signal on the side thread.
2176       raise_debugger_signal(kDebuggerdNativeBacktrace);
2177     });
2178     thread.join();
2179     _exit(0);
2180   });
2181 
2182   unique_fd output_fd;
2183   StartIntercept(&output_fd, kDebuggerdNativeBacktrace);
2184   FinishCrasher();
2185   AssertDeath(0);
2186 
2187   int intercept_result;
2188   FinishIntercept(&intercept_result);
2189   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2190 
2191   std::string result;
2192   ConsumeFd(std::move(output_fd), &result);
2193   ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
2194 }
2195 
format_pointer(uintptr_t ptr)2196 static std::string format_pointer(uintptr_t ptr) {
2197 #if defined(__LP64__)
2198   return android::base::StringPrintf("%08x'%08x", static_cast<uint32_t>(ptr >> 32),
2199                                      static_cast<uint32_t>(ptr & 0xffffffff));
2200 #else
2201   return android::base::StringPrintf("%08x", static_cast<uint32_t>(ptr & 0xffffffff));
2202 #endif
2203 }
2204 
format_pointer(void * ptr)2205 static std::string format_pointer(void* ptr) {
2206   return format_pointer(reinterpret_cast<uintptr_t>(ptr));
2207 }
2208 
format_full_pointer(uintptr_t ptr)2209 static std::string format_full_pointer(uintptr_t ptr) {
2210 #if defined(__LP64__)
2211   return android::base::StringPrintf("%016" PRIx64, ptr);
2212 #else
2213   return android::base::StringPrintf("%08x", ptr);
2214 #endif
2215 }
2216 
format_full_pointer(void * ptr)2217 static std::string format_full_pointer(void* ptr) {
2218   return format_full_pointer(reinterpret_cast<uintptr_t>(ptr));
2219 }
2220 
crash_call(uintptr_t ptr)2221 __attribute__((__noinline__)) int crash_call(uintptr_t ptr) {
2222   int* crash_ptr = reinterpret_cast<int*>(ptr);
2223   *crash_ptr = 1;
2224   return *crash_ptr;
2225 }
2226 
2227 // Verify that a fault address before the first map is properly handled.
TEST_F(CrasherTest,fault_address_before_first_map)2228 TEST_F(CrasherTest, fault_address_before_first_map) {
2229   StartProcess([]() {
2230     ASSERT_EQ(0, crash_call(0x1024));
2231     _exit(0);
2232   });
2233 
2234   unique_fd output_fd;
2235   StartIntercept(&output_fd);
2236   FinishCrasher();
2237   AssertDeath(SIGSEGV);
2238 
2239   int intercept_result;
2240   FinishIntercept(&intercept_result);
2241   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2242 
2243   std::string result;
2244   ConsumeFd(std::move(output_fd), &result);
2245   ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+1024)");
2246 
2247   ASSERT_MATCH(result, R"(\nmemory map \(.*\):\n)");
2248 
2249   std::string match_str = android::base::StringPrintf(
2250       R"(memory map .*:\n--->Fault address falls at %s before any mapped regions\n    )",
2251       format_pointer(0x1024).c_str());
2252   ASSERT_MATCH(result, match_str);
2253 }
2254 
2255 // Verify that a fault address after the last map is properly handled.
TEST_F(CrasherTest,fault_address_after_last_map)2256 TEST_F(CrasherTest, fault_address_after_last_map) {
2257   // This makes assumptions about the memory layout that are not true in HWASan
2258   // processes.
2259   SKIP_WITH_HWASAN;
2260   uintptr_t crash_uptr = untag_address(UINTPTR_MAX - 15);
2261   StartProcess([crash_uptr]() {
2262     ASSERT_EQ(0, crash_call(crash_uptr));
2263     _exit(0);
2264   });
2265 
2266   unique_fd output_fd;
2267   StartIntercept(&output_fd);
2268   FinishCrasher();
2269   AssertDeath(SIGSEGV);
2270 
2271   int intercept_result;
2272   FinishIntercept(&intercept_result);
2273   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2274 
2275   std::string result;
2276   ConsumeFd(std::move(output_fd), &result);
2277 
2278   std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x)";
2279   match_str += format_full_pointer(crash_uptr);
2280   ASSERT_MATCH(result, match_str);
2281 
2282   ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
2283 
2284   // Assumes that the open files section comes after the map section.
2285   // If that assumption changes, the regex below needs to change.
2286   match_str = android::base::StringPrintf(
2287       R"(\n--->Fault address falls at %s after any mapped regions\n\nopen files:)",
2288       format_pointer(crash_uptr).c_str());
2289   ASSERT_MATCH(result, match_str);
2290 }
2291 
2292 // Verify that a fault address between maps is properly handled.
TEST_F(CrasherTest,fault_address_between_maps)2293 TEST_F(CrasherTest, fault_address_between_maps) {
2294   // Create a map before the fork so it will be present in the child.
2295   void* start_ptr =
2296       mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2297   ASSERT_NE(MAP_FAILED, start_ptr);
2298   // Unmap the page in the middle.
2299   void* middle_ptr =
2300       reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start_ptr) + getpagesize());
2301   ASSERT_EQ(0, munmap(middle_ptr, getpagesize()));
2302 
2303   StartProcess([middle_ptr]() {
2304     ASSERT_EQ(0, crash_call(reinterpret_cast<uintptr_t>(middle_ptr)));
2305     _exit(0);
2306   });
2307 
2308   // Unmap the two maps.
2309   ASSERT_EQ(0, munmap(start_ptr, getpagesize()));
2310   void* end_ptr =
2311       reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start_ptr) + 2 * getpagesize());
2312   ASSERT_EQ(0, munmap(end_ptr, getpagesize()));
2313 
2314   unique_fd output_fd;
2315   StartIntercept(&output_fd);
2316   FinishCrasher();
2317   AssertDeath(SIGSEGV);
2318 
2319   int intercept_result;
2320   FinishIntercept(&intercept_result);
2321   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2322 
2323   std::string result;
2324   ConsumeFd(std::move(output_fd), &result);
2325 
2326   std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x)";
2327   match_str += format_full_pointer(reinterpret_cast<uintptr_t>(middle_ptr));
2328   ASSERT_MATCH(result, match_str);
2329 
2330   ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
2331 
2332   match_str = android::base::StringPrintf(
2333       R"(    %s.*\n--->Fault address falls at %s between mapped regions\n    %s)",
2334       format_pointer(start_ptr).c_str(), format_pointer(middle_ptr).c_str(),
2335       format_pointer(end_ptr).c_str());
2336   ASSERT_MATCH(result, match_str);
2337 }
2338 
2339 // Verify that a fault address happens in the correct map.
TEST_F(CrasherTest,fault_address_in_map)2340 TEST_F(CrasherTest, fault_address_in_map) {
2341   // Create a map before the fork so it will be present in the child.
2342   void* ptr = mmap(nullptr, getpagesize(), 0, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2343   ASSERT_NE(MAP_FAILED, ptr);
2344 
2345   StartProcess([ptr]() {
2346     ASSERT_EQ(0, crash_call(reinterpret_cast<uintptr_t>(ptr)));
2347     _exit(0);
2348   });
2349 
2350   ASSERT_EQ(0, munmap(ptr, getpagesize()));
2351 
2352   unique_fd output_fd;
2353   StartIntercept(&output_fd);
2354   FinishCrasher();
2355   AssertDeath(SIGSEGV);
2356 
2357   int intercept_result;
2358   FinishIntercept(&intercept_result);
2359   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2360 
2361   std::string result;
2362   ConsumeFd(std::move(output_fd), &result);
2363 
2364   std::string match_str = R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\), fault addr 0x)";
2365   match_str += format_full_pointer(reinterpret_cast<uintptr_t>(ptr));
2366   ASSERT_MATCH(result, match_str);
2367 
2368   ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
2369 
2370   match_str = android::base::StringPrintf(R"(\n--->%s.*\n)", format_pointer(ptr).c_str());
2371   ASSERT_MATCH(result, match_str);
2372 }
2373 
2374 static constexpr uint32_t kDexData[] = {
2375     0x0a786564, 0x00383330, 0xc98b3ab8, 0xf3749d94, 0xaecca4d8, 0xffc7b09a, 0xdca9ca7f, 0x5be5deab,
2376     0x00000220, 0x00000070, 0x12345678, 0x00000000, 0x00000000, 0x0000018c, 0x00000008, 0x00000070,
2377     0x00000004, 0x00000090, 0x00000002, 0x000000a0, 0x00000000, 0x00000000, 0x00000003, 0x000000b8,
2378     0x00000001, 0x000000d0, 0x00000130, 0x000000f0, 0x00000122, 0x0000012a, 0x00000132, 0x00000146,
2379     0x00000151, 0x00000154, 0x00000158, 0x0000016d, 0x00000001, 0x00000002, 0x00000004, 0x00000006,
2380     0x00000004, 0x00000002, 0x00000000, 0x00000005, 0x00000002, 0x0000011c, 0x00000000, 0x00000000,
2381     0x00010000, 0x00000007, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000,
2382     0x00000003, 0x00000000, 0x0000017e, 0x00000000, 0x00010001, 0x00000001, 0x00000173, 0x00000004,
2383     0x00021070, 0x000e0000, 0x00010001, 0x00000000, 0x00000178, 0x00000001, 0x0000000e, 0x00000001,
2384     0x3c060003, 0x74696e69, 0x4c06003e, 0x6e69614d, 0x4c12003b, 0x6176616a, 0x6e616c2f, 0x624f2f67,
2385     0x7463656a, 0x4d09003b, 0x2e6e6961, 0x6176616a, 0x00560100, 0x004c5602, 0x6a4c5b13, 0x2f617661,
2386     0x676e616c, 0x7274532f, 0x3b676e69, 0x616d0400, 0x01006e69, 0x000e0700, 0x07000103, 0x0000000e,
2387     0x81000002, 0x01f00480, 0x02880901, 0x0000000c, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
2388     0x00000008, 0x00000070, 0x00000002, 0x00000004, 0x00000090, 0x00000003, 0x00000002, 0x000000a0,
2389     0x00000005, 0x00000003, 0x000000b8, 0x00000006, 0x00000001, 0x000000d0, 0x00002001, 0x00000002,
2390     0x000000f0, 0x00001001, 0x00000001, 0x0000011c, 0x00002002, 0x00000008, 0x00000122, 0x00002003,
2391     0x00000002, 0x00000173, 0x00002000, 0x00000001, 0x0000017e, 0x00001000, 0x00000001, 0x0000018c,
2392 };
2393 
TEST_F(CrasherTest,verify_dex_pc_with_function_name)2394 TEST_F(CrasherTest, verify_dex_pc_with_function_name) {
2395   StartProcess([]() {
2396     TemporaryDir td;
2397     std::string tmp_so_name;
2398     if (!CopySharedLibrary(td.path, &tmp_so_name)) {
2399       _exit(1);
2400     }
2401 
2402     // In order to cause libunwindstack to look for this __dex_debug_descriptor
2403     // move the library to which has a basename of libart.so.
2404     std::string art_so_name = android::base::Dirname(tmp_so_name) + "/libart.so";
2405     ASSERT_EQ(0, rename(tmp_so_name.c_str(), art_so_name.c_str()));
2406     void* handle = dlopen(art_so_name.c_str(), RTLD_NOW | RTLD_LOCAL);
2407     if (handle == nullptr) {
2408       _exit(1);
2409     }
2410 
2411     void* ptr =
2412         mmap(nullptr, sizeof(kDexData), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2413     ASSERT_TRUE(ptr != MAP_FAILED);
2414     memcpy(ptr, kDexData, sizeof(kDexData));
2415     prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, sizeof(kDexData), "dex");
2416 
2417     JITCodeEntry dex_entry = {.symfile_addr = reinterpret_cast<uintptr_t>(ptr),
2418                               .symfile_size = sizeof(kDexData)};
2419 
2420     JITDescriptor* dex_debug =
2421         reinterpret_cast<JITDescriptor*>(dlsym(handle, "__dex_debug_descriptor"));
2422     ASSERT_TRUE(dex_debug != nullptr);
2423     dex_debug->version = 1;
2424     dex_debug->action_flag = 0;
2425     dex_debug->relevant_entry = 0;
2426     dex_debug->first_entry = reinterpret_cast<uintptr_t>(&dex_entry);
2427 
2428     // This sets the magic dex pc value for register 0, using the value
2429     // of register 1 + 0x102.
2430     asm(".cfi_escape "
2431         "0x16 /* DW_CFA_val_expression */, 0, 0x0a /* size */,"
2432         "0x0c /* DW_OP_const4u */, 0x44, 0x45, 0x58, 0x31, /* magic = 'DEX1' */"
2433         "0x13 /* DW_OP_drop */,"
2434         "0x92 /* DW_OP_bregx */, 1, 0x82, 0x02 /* 2-byte SLEB128 */");
2435 
2436     // For each different architecture, set register one to the dex ptr mmap
2437     // created above. Then do a nullptr dereference to force a crash.
2438 #if defined(__arm__)
2439     asm volatile(
2440         "mov r1, %[base]\n"
2441         "mov r2, #0\n"
2442         "str r2, [r2]\n"
2443         : [base] "+r"(ptr)
2444         :
2445         : "r1", "r2", "memory");
2446 #elif defined(__aarch64__)
2447     asm volatile(
2448         "mov x1, %[base]\n"
2449         "mov x2, #0\n"
2450         "str xzr, [x2]\n"
2451         : [base] "+r"(ptr)
2452         :
2453         : "x1", "x2", "memory");
2454 #elif defined(__riscv)
2455     // TODO: x1 is ra (the link register) on riscv64, so this might have
2456     // unintended consequences, but we'll need to change the .cfi_escape if so.
2457     asm volatile(
2458         "mv x1, %[base]\n"
2459         "sw zero, 0(zero)\n"
2460         : [base] "+r"(ptr)
2461         :
2462         : "x1", "memory");
2463 #elif defined(__i386__)
2464     asm volatile(
2465         "mov %[base], %%ecx\n"
2466         "movl $0, 0\n"
2467         : [base] "+r"(ptr)
2468         :
2469         : "ecx", "memory");
2470 #elif defined(__x86_64__)
2471     asm volatile(
2472         "mov %[base], %%rdx\n"
2473         "movq $0, 0\n"
2474         : [base] "+r"(ptr)
2475         :
2476         : "rdx", "memory");
2477 #else
2478 #error "Unsupported architecture"
2479 #endif
2480     _exit(0);
2481   });
2482 
2483   unique_fd output_fd;
2484   StartIntercept(&output_fd);
2485   FinishCrasher();
2486   AssertDeath(SIGSEGV);
2487 
2488   int intercept_result;
2489   FinishIntercept(&intercept_result);
2490   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2491 
2492   std::string result;
2493   ConsumeFd(std::move(output_fd), &result);
2494 
2495   // Verify the process crashed properly.
2496   ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0*)");
2497 
2498   // Now verify that the dex_pc frame includes a proper function name.
2499   ASSERT_MATCH(result, R"( \[anon:dex\] \(Main\.\<init\>\+2)");
2500 }
2501 
format_map_pointer(uintptr_t ptr)2502 static std::string format_map_pointer(uintptr_t ptr) {
2503 #if defined(__LP64__)
2504   return android::base::StringPrintf("%08x'%08x", static_cast<uint32_t>(ptr >> 32),
2505                                      static_cast<uint32_t>(ptr & 0xffffffff));
2506 #else
2507   return android::base::StringPrintf("%08x", ptr);
2508 #endif
2509 }
2510 
2511 // Verify that map data is properly formatted.
TEST_F(CrasherTest,verify_map_format)2512 TEST_F(CrasherTest, verify_map_format) {
2513   // Create multiple maps to make sure that the map data is formatted properly.
2514   void* none_map = mmap(nullptr, getpagesize(), 0, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2515   ASSERT_NE(MAP_FAILED, none_map);
2516   void* r_map = mmap(nullptr, getpagesize(), PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2517   ASSERT_NE(MAP_FAILED, r_map);
2518   void* w_map = mmap(nullptr, getpagesize(), PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2519   ASSERT_NE(MAP_FAILED, w_map);
2520   void* x_map = mmap(nullptr, getpagesize(), PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2521   ASSERT_NE(MAP_FAILED, x_map);
2522 
2523   TemporaryFile tf;
2524   ASSERT_EQ(0x2000, lseek(tf.fd, 0x2000, SEEK_SET));
2525   char c = 'f';
2526   ASSERT_EQ(1, write(tf.fd, &c, 1));
2527   ASSERT_EQ(0x5000, lseek(tf.fd, 0x5000, SEEK_SET));
2528   ASSERT_EQ(1, write(tf.fd, &c, 1));
2529   ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
2530   void* file_map = mmap(nullptr, 0x3001, PROT_READ, MAP_PRIVATE, tf.fd, 0x2000);
2531   ASSERT_NE(MAP_FAILED, file_map);
2532 
2533   StartProcess([]() { abort(); });
2534 
2535   ASSERT_EQ(0, munmap(none_map, getpagesize()));
2536   ASSERT_EQ(0, munmap(r_map, getpagesize()));
2537   ASSERT_EQ(0, munmap(w_map, getpagesize()));
2538   ASSERT_EQ(0, munmap(x_map, getpagesize()));
2539   ASSERT_EQ(0, munmap(file_map, 0x3001));
2540 
2541   unique_fd output_fd;
2542   StartIntercept(&output_fd);
2543   FinishCrasher();
2544   AssertDeath(SIGABRT);
2545   int intercept_result;
2546   FinishIntercept(&intercept_result);
2547 
2548   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2549 
2550   std::string result;
2551   ConsumeFd(std::move(output_fd), &result);
2552 
2553   std::string match_str;
2554   // Verify none.
2555   match_str = android::base::StringPrintf(
2556       "    %s-%s ---         0      1000\\n",
2557       format_map_pointer(reinterpret_cast<uintptr_t>(none_map)).c_str(),
2558       format_map_pointer(reinterpret_cast<uintptr_t>(none_map) + getpagesize() - 1).c_str());
2559   ASSERT_MATCH(result, match_str);
2560 
2561   // Verify read-only.
2562   match_str = android::base::StringPrintf(
2563       "    %s-%s r--         0      1000\\n",
2564       format_map_pointer(reinterpret_cast<uintptr_t>(r_map)).c_str(),
2565       format_map_pointer(reinterpret_cast<uintptr_t>(r_map) + getpagesize() - 1).c_str());
2566   ASSERT_MATCH(result, match_str);
2567 
2568   // Verify write-only.
2569   match_str = android::base::StringPrintf(
2570       "    %s-%s -w-         0      1000\\n",
2571       format_map_pointer(reinterpret_cast<uintptr_t>(w_map)).c_str(),
2572       format_map_pointer(reinterpret_cast<uintptr_t>(w_map) + getpagesize() - 1).c_str());
2573   ASSERT_MATCH(result, match_str);
2574 
2575   // Verify exec-only.
2576   match_str = android::base::StringPrintf(
2577       "    %s-%s --x         0      1000\\n",
2578       format_map_pointer(reinterpret_cast<uintptr_t>(x_map)).c_str(),
2579       format_map_pointer(reinterpret_cast<uintptr_t>(x_map) + getpagesize() - 1).c_str());
2580   ASSERT_MATCH(result, match_str);
2581 
2582   // Verify file map with non-zero offset and a name.
2583   match_str = android::base::StringPrintf(
2584       "    %s-%s r--      2000      4000  %s\\n",
2585       format_map_pointer(reinterpret_cast<uintptr_t>(file_map)).c_str(),
2586       format_map_pointer(reinterpret_cast<uintptr_t>(file_map) + 0x3fff).c_str(), tf.path);
2587   ASSERT_MATCH(result, match_str);
2588 }
2589 
2590 // Verify that the tombstone map data is correct.
TEST_F(CrasherTest,verify_header)2591 TEST_F(CrasherTest, verify_header) {
2592   StartProcess([]() { abort(); });
2593 
2594   unique_fd output_fd;
2595   StartIntercept(&output_fd);
2596   FinishCrasher();
2597   AssertDeath(SIGABRT);
2598   int intercept_result;
2599   FinishIntercept(&intercept_result);
2600 
2601   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2602 
2603   std::string result;
2604   ConsumeFd(std::move(output_fd), &result);
2605 
2606   std::string match_str = android::base::StringPrintf(
2607       "Build fingerprint: '%s'\\nRevision: '%s'\\n",
2608       android::base::GetProperty("ro.build.fingerprint", "unknown").c_str(),
2609       android::base::GetProperty("ro.revision", "unknown").c_str());
2610   match_str += android::base::StringPrintf("ABI: '%s'\n", ABI_STRING);
2611   ASSERT_MATCH(result, match_str);
2612 }
2613 
2614 // Verify that the thread header is formatted properly.
TEST_F(CrasherTest,verify_thread_header)2615 TEST_F(CrasherTest, verify_thread_header) {
2616   void* shared_map =
2617       mmap(nullptr, sizeof(pid_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
2618   ASSERT_NE(MAP_FAILED, shared_map);
2619   memset(shared_map, 0, sizeof(pid_t));
2620 
2621   StartProcess([&shared_map]() {
2622     std::atomic_bool tid_written;
2623     std::thread thread([&tid_written, &shared_map]() {
2624       pid_t tid = gettid();
2625       memcpy(shared_map, &tid, sizeof(pid_t));
2626       tid_written = true;
2627       volatile bool done = false;
2628       while (!done)
2629         ;
2630     });
2631     thread.detach();
2632     while (!tid_written.load(std::memory_order_acquire))
2633       ;
2634     abort();
2635   });
2636 
2637   pid_t primary_pid = crasher_pid;
2638 
2639   unique_fd output_fd;
2640   StartIntercept(&output_fd);
2641   FinishCrasher();
2642   AssertDeath(SIGABRT);
2643   int intercept_result;
2644   FinishIntercept(&intercept_result);
2645   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2646 
2647   // Read the tid data out.
2648   pid_t tid;
2649   memcpy(&tid, shared_map, sizeof(pid_t));
2650   ASSERT_NE(0, tid);
2651 
2652   ASSERT_EQ(0, munmap(shared_map, sizeof(pid_t)));
2653 
2654   std::string result;
2655   ConsumeFd(std::move(output_fd), &result);
2656 
2657   // Verify that there are two headers, one where the tid is "primary_pid"
2658   // and the other where the tid is "tid".
2659   std::string match_str = android::base::StringPrintf("pid: %d, tid: %d, name: .*  >>> .* <<<\\n",
2660                                                       primary_pid, primary_pid);
2661   ASSERT_MATCH(result, match_str);
2662 
2663   match_str =
2664       android::base::StringPrintf("pid: %d, tid: %d, name: .*  >>> .* <<<\\n", primary_pid, tid);
2665   ASSERT_MATCH(result, match_str);
2666 }
2667 
2668 // Verify that there is a BuildID present in the map section and set properly.
TEST_F(CrasherTest,verify_build_id)2669 TEST_F(CrasherTest, verify_build_id) {
2670   StartProcess([]() { abort(); });
2671 
2672   unique_fd output_fd;
2673   StartIntercept(&output_fd);
2674   FinishCrasher();
2675   AssertDeath(SIGABRT);
2676   int intercept_result;
2677   FinishIntercept(&intercept_result);
2678   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2679 
2680   std::string result;
2681   ConsumeFd(std::move(output_fd), &result);
2682 
2683   // Find every /system or /apex lib and verify the BuildID is displayed
2684   // properly.
2685   bool found_valid_elf = false;
2686   std::smatch match;
2687   std::regex build_id_regex(R"(  ((/system/|/apex/)\S+) \(BuildId: ([^\)]+)\))");
2688   for (std::string prev_file; std::regex_search(result, match, build_id_regex);
2689        result = match.suffix()) {
2690     if (prev_file == match[1]) {
2691       // Already checked this file.
2692       continue;
2693     }
2694 
2695     prev_file = match[1];
2696     unwindstack::Elf elf(unwindstack::Memory::CreateFileMemory(prev_file, 0).release());
2697     if (!elf.Init() || !elf.valid()) {
2698       // Skipping invalid elf files.
2699       continue;
2700     }
2701     ASSERT_EQ(match[3], elf.GetPrintableBuildID());
2702 
2703     found_valid_elf = true;
2704   }
2705   ASSERT_TRUE(found_valid_elf) << "Did not find any elf files with valid BuildIDs to check.";
2706 }
2707 
2708 const char kLogMessage[] = "Should not see this log message.";
2709 
2710 // Verify that the logd process does not read the log.
TEST_F(CrasherTest,logd_skips_reading_logs)2711 TEST_F(CrasherTest, logd_skips_reading_logs) {
2712   StartProcess([]() {
2713     pthread_setname_np(pthread_self(), "logd");
2714     LOG(INFO) << kLogMessage;
2715     abort();
2716   });
2717 
2718   unique_fd output_fd;
2719   StartIntercept(&output_fd);
2720   FinishCrasher();
2721   AssertDeath(SIGABRT);
2722   int intercept_result;
2723   FinishIntercept(&intercept_result);
2724   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2725 
2726   std::string result;
2727   ConsumeFd(std::move(output_fd), &result);
2728   // logd should not contain our log message.
2729   ASSERT_NOT_MATCH(result, kLogMessage);
2730 }
2731 
2732 // Verify that the logd process does not read the log when the non-main
2733 // thread crashes.
TEST_F(CrasherTest,logd_skips_reading_logs_not_main_thread)2734 TEST_F(CrasherTest, logd_skips_reading_logs_not_main_thread) {
2735   StartProcess([]() {
2736     pthread_setname_np(pthread_self(), "logd");
2737     LOG(INFO) << kLogMessage;
2738 
2739     std::thread thread([]() {
2740       pthread_setname_np(pthread_self(), "not_logd_thread");
2741       // Raise the signal on the side thread.
2742       raise_debugger_signal(kDebuggerdTombstone);
2743     });
2744     thread.join();
2745     _exit(0);
2746   });
2747 
2748   unique_fd output_fd;
2749   StartIntercept(&output_fd, kDebuggerdTombstone);
2750   FinishCrasher();
2751   AssertDeath(0);
2752 
2753   int intercept_result;
2754   FinishIntercept(&intercept_result);
2755   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2756 
2757   std::string result;
2758   ConsumeFd(std::move(output_fd), &result);
2759   ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
2760   ASSERT_NOT_MATCH(result, kLogMessage);
2761 }
2762 
2763 // Disable this test since there is a high liklihood that this would
2764 // be flaky since it requires 500 messages being in the log.
TEST_F(CrasherTest,DISABLED_max_log_messages)2765 TEST_F(CrasherTest, DISABLED_max_log_messages) {
2766   StartProcess([]() {
2767     for (size_t i = 0; i < 600; i++) {
2768       LOG(INFO) << "Message number " << i;
2769     }
2770     abort();
2771   });
2772 
2773   unique_fd output_fd;
2774   StartIntercept(&output_fd);
2775   FinishCrasher();
2776   AssertDeath(SIGABRT);
2777   int intercept_result;
2778   FinishIntercept(&intercept_result);
2779   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2780 
2781   std::string result;
2782   ConsumeFd(std::move(output_fd), &result);
2783   ASSERT_NOT_MATCH(result, "Message number 99");
2784   ASSERT_MATCH(result, "Message number 100");
2785   ASSERT_MATCH(result, "Message number 599");
2786 }
2787 
TEST_F(CrasherTest,log_with_newline)2788 TEST_F(CrasherTest, log_with_newline) {
2789   StartProcess([]() {
2790     LOG(INFO) << "This line has a newline.\nThis is on the next line.";
2791     abort();
2792   });
2793 
2794   unique_fd output_fd;
2795   StartIntercept(&output_fd);
2796   FinishCrasher();
2797   AssertDeath(SIGABRT);
2798   int intercept_result;
2799   FinishIntercept(&intercept_result);
2800   ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2801 
2802   std::string result;
2803   ConsumeFd(std::move(output_fd), &result);
2804   ASSERT_MATCH(result, ":\\s*This line has a newline.");
2805   ASSERT_MATCH(result, ":\\s*This is on the next line.");
2806 }
2807