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