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