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