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