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