blob: a308ffbc91ec54be3c5ce109ec36edfa99c855fd [file] [log] [blame]
Josh Gaocbe70cb2016-10-18 18:17:52 -07001/*
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
Christopher Ferris35da2882021-02-17 15:39:06 -080017#include <dirent.h>
Christopher Ferrisfe751c52021-04-16 09:40:40 -070018#include <dlfcn.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070019#include <err.h>
20#include <fcntl.h>
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +000021#include <linux/prctl.h>
Elliott Hughes03b283a2021-01-15 11:34:26 -080022#include <malloc.h>
Christopher Ferrisbda10642023-04-24 18:14:53 -070023#include <pthread.h>
Josh Gaocdea7502017-11-01 15:00:40 -070024#include <stdlib.h>
Josh Gao502cfd22017-02-17 01:39:15 -080025#include <sys/capability.h>
Peter Collingbournefe8997a2020-07-20 15:08:52 -070026#include <sys/mman.h>
Josh Gaofca7ca32017-01-23 12:05:35 -080027#include <sys/prctl.h>
Josh Gaofd13bf02017-08-18 15:37:26 -070028#include <sys/ptrace.h>
Josh Gao70adac62018-02-22 11:38:33 -080029#include <sys/resource.h>
Dan Albertc38057a2017-10-11 11:35:40 -070030#include <sys/syscall.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070031#include <sys/types.h>
Josh Gaofd13bf02017-08-18 15:37:26 -070032#include <unistd.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070033
34#include <chrono>
35#include <regex>
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +000036#include <set>
Christopher Ferrisfe751c52021-04-16 09:40:40 -070037#include <string>
Josh Gaocbe70cb2016-10-18 18:17:52 -070038#include <thread>
39
Christopher Ferris22035cc2023-01-31 17:50:22 -080040#include <android/dlext.h>
Josh Gaobf06a402018-08-27 16:34:01 -070041#include <android/fdsan.h>
Josh Gao502cfd22017-02-17 01:39:15 -080042#include <android/set_abort_message.h>
Mitch Phillips7168a212021-03-09 16:53:23 -080043#include <bionic/malloc.h>
Peter Collingbournef8622522020-04-07 14:07:32 -070044#include <bionic/mte.h>
Josh Gaoa48b41b2019-12-13 14:11:04 -080045#include <bionic/reserved_signals.h>
Josh Gao502cfd22017-02-17 01:39:15 -080046
Josh Gao5f87bbd2019-01-09 17:01:49 -080047#include <android-base/cmsg.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070048#include <android-base/file.h>
49#include <android-base/logging.h>
Josh Gao2e7b8e22017-05-04 17:12:57 -070050#include <android-base/macros.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070051#include <android-base/parseint.h>
52#include <android-base/properties.h>
Josh Gao2b22ae12018-09-12 14:51:03 -070053#include <android-base/stringprintf.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070054#include <android-base/strings.h>
Josh Gao30171a82017-04-27 19:48:44 -070055#include <android-base/test_utils.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070056#include <android-base/unique_fd.h>
57#include <cutils/sockets.h>
Mitch Phillips78f06702021-06-01 14:35:43 -070058#include <gmock/gmock.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070059#include <gtest/gtest.h>
60
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +000061#include <unwindstack/Elf.h>
62#include <unwindstack/Memory.h>
63
Josh Gaoe04ca272018-01-16 15:38:17 -080064#include <libminijail.h>
65#include <scoped_minijail.h>
66
Christopher Ferris2038cc72021-09-15 03:57:10 +000067#include "crash_test.h"
Narayan Kamath2d377cd2017-05-10 10:58:59 +010068#include "debuggerd/handler.h"
Mitch Phillips18ce5422023-01-19 14:23:49 -080069#include "gtest/gtest.h"
Mitch Phillips5ddcea22021-04-19 09:59:17 -070070#include "libdebuggerd/utility.h"
Narayan Kamath2d377cd2017-05-10 10:58:59 +010071#include "protocol.h"
72#include "tombstoned/tombstoned.h"
73#include "util.h"
74
Josh Gaocbe70cb2016-10-18 18:17:52 -070075using namespace std::chrono_literals;
Josh Gao5f87bbd2019-01-09 17:01:49 -080076
77using android::base::SendFileDescriptors;
Josh Gaocbe70cb2016-10-18 18:17:52 -070078using android::base::unique_fd;
Mitch Phillips78f06702021-06-01 14:35:43 -070079using ::testing::HasSubstr;
Josh Gaocbe70cb2016-10-18 18:17:52 -070080
81#if defined(__LP64__)
Josh Gaocbe70cb2016-10-18 18:17:52 -070082#define ARCH_SUFFIX "64"
83#else
Josh Gaocbe70cb2016-10-18 18:17:52 -070084#define ARCH_SUFFIX ""
85#endif
86
Elliott Hughese4781d52021-03-17 09:15:15 -070087constexpr char kWaitForDebuggerKey[] = "debug.debuggerd.wait_for_debugger";
Josh Gaocbe70cb2016-10-18 18:17:52 -070088
89#define TIMEOUT(seconds, expr) \
90 [&]() { \
91 struct sigaction old_sigaction; \
92 struct sigaction new_sigaction = {}; \
93 new_sigaction.sa_handler = [](int) {}; \
Christopher Ferris16a7bc22022-01-31 13:08:54 -080094 if (sigaction(SIGALRM, &new_sigaction, &old_sigaction) != 0) { \
Josh Gaocbe70cb2016-10-18 18:17:52 -070095 err(1, "sigaction failed"); \
96 } \
Mattias Simonsson38ab0452023-11-08 12:02:46 +000097 alarm(seconds * android::base::HwTimeoutMultiplier()); \
Josh Gaocbe70cb2016-10-18 18:17:52 -070098 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
Chih-Hung Hsieh3249b3a2018-05-11 16:01:21 -0700108// 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)
Josh Gaoe04ca272018-01-16 15:38:17 -0800112#define ASSERT_BACKTRACE_FRAME(result, frame_name) \
Chih-Hung Hsieh3249b3a2018-05-11 16:01:21 -0700113 ASSERT_MATCH(result, \
114 R"(#\d\d pc [0-9a-f]+\s+ \S+ (\(offset 0x[0-9a-f]+\) )?\()" frame_name R"(\+)");
Jaesung Chung58778e12017-06-15 18:20:34 +0900115
Narayan Kamatha73df602017-05-24 15:07:25 +0100116static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, unique_fd* output_fd,
Christopher Ferrisb92b52c2023-10-16 19:14:28 -0700117 InterceptResponse* response, DebuggerdDumpType intercept_type) {
Josh Gao460b3362017-03-30 16:40:47 -0700118 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
Nick Desaulniers67d52aa2019-10-07 23:28:15 -0700124 InterceptRequest req = {
125 .dump_type = intercept_type,
126 .pid = target_pid,
127 };
Josh Gao460b3362017-03-30 16:40:47 -0700128
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
Josh Gao5675f3c2017-06-01 12:19:53 -0700150 ASSERT_GE(pipe_buffer_size, 1024 * 1024);
151
Josh Gao5f87bbd2019-01-09 17:01:49 -0800152 ssize_t rc = SendFileDescriptors(intercept_fd->get(), &req, sizeof(req), output_pipe_write.get());
153 output_pipe_write.reset();
154 if (rc != sizeof(req)) {
Josh Gao460b3362017-03-30 16:40:47 -0700155 FAIL() << "failed to send output fd to tombstoned: " << strerror(errno);
156 }
157
Christopher Ferrisb92b52c2023-10-16 19:14:28 -0700158 rc = TEMP_FAILURE_RETRY(read(intercept_fd->get(), response, sizeof(*response)));
Josh Gao460b3362017-03-30 16:40:47 -0700159 if (rc == -1) {
160 FAIL() << "failed to read response from tombstoned: " << strerror(errno);
161 } else if (rc == 0) {
162 FAIL() << "failed to read response from tombstoned (EOF)";
Christopher Ferrisb92b52c2023-10-16 19:14:28 -0700163 } else if (rc != sizeof(*response)) {
164 FAIL() << "received packet of unexpected length from tombstoned: expected " << sizeof(*response)
Josh Gao460b3362017-03-30 16:40:47 -0700165 << ", received " << rc;
166 }
Josh Gao460b3362017-03-30 16:40:47 -0700167}
168
Elliott Hughesd13ea522022-01-13 09:20:26 -0800169static bool pac_supported() {
170#if defined(__aarch64__)
171 return getauxval(AT_HWCAP) & HWCAP_PACA;
172#else
173 return false;
174#endif
175}
176
Josh Gaocbe70cb2016-10-18 18:17:52 -0700177class CrasherTest : public ::testing::Test {
178 public:
179 pid_t crasher_pid = -1;
Elliott Hughese4781d52021-03-17 09:15:15 -0700180 bool previous_wait_for_debugger;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700181 unique_fd crasher_pipe;
182 unique_fd intercept_fd;
183
184 CrasherTest();
185 ~CrasherTest();
186
Narayan Kamatha73df602017-05-24 15:07:25 +0100187 void StartIntercept(unique_fd* output_fd, DebuggerdDumpType intercept_type = kDebuggerdTombstone);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700188
189 // Returns -1 if we fail to read a response from tombstoned, otherwise the received return code.
190 void FinishIntercept(int* result);
191
Josh Gao2e7b8e22017-05-04 17:12:57 -0700192 void StartProcess(std::function<void()> function, std::function<pid_t()> forker = fork);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700193 void StartCrasher(const std::string& crash_type);
194 void FinishCrasher();
195 void AssertDeath(int signo);
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700196
197 static void Trap(void* ptr);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700198};
199
200CrasherTest::CrasherTest() {
Elliott Hughese4781d52021-03-17 09:15:15 -0700201 previous_wait_for_debugger = android::base::GetBoolProperty(kWaitForDebuggerKey, false);
202 android::base::SetProperty(kWaitForDebuggerKey, "0");
203
204 // Clear the old property too, just in case someone's been using it
205 // on this device. (We only document the new name, but we still support
206 // the old name so we don't break anyone's existing setups.)
207 android::base::SetProperty("debug.debuggerd.wait_for_gdb", "0");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700208}
209
210CrasherTest::~CrasherTest() {
211 if (crasher_pid != -1) {
212 kill(crasher_pid, SIGKILL);
213 int status;
Christopher Ferris172b0a02019-09-18 17:48:30 -0700214 TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, WUNTRACED));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700215 }
216
Elliott Hughese4781d52021-03-17 09:15:15 -0700217 android::base::SetProperty(kWaitForDebuggerKey, previous_wait_for_debugger ? "1" : "0");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700218}
219
Narayan Kamatha73df602017-05-24 15:07:25 +0100220void CrasherTest::StartIntercept(unique_fd* output_fd, DebuggerdDumpType intercept_type) {
Josh Gaocbe70cb2016-10-18 18:17:52 -0700221 if (crasher_pid == -1) {
222 FAIL() << "crasher hasn't been started";
223 }
224
Christopher Ferrisb92b52c2023-10-16 19:14:28 -0700225 InterceptResponse response = {};
226 tombstoned_intercept(crasher_pid, &this->intercept_fd, output_fd, &response, intercept_type);
227 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
228 << "Error message: " << response.error_message;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700229}
230
231void CrasherTest::FinishIntercept(int* result) {
232 InterceptResponse response;
233
Christopher Ferris11555f02019-09-20 14:18:55 -0700234 ssize_t rc = TIMEOUT(30, read(intercept_fd.get(), &response, sizeof(response)));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700235 if (rc == -1) {
236 FAIL() << "failed to read response from tombstoned: " << strerror(errno);
237 } else if (rc == 0) {
238 *result = -1;
239 } else if (rc != sizeof(response)) {
240 FAIL() << "received packet of unexpected length from tombstoned: expected " << sizeof(response)
241 << ", received " << rc;
242 } else {
Josh Gao460b3362017-03-30 16:40:47 -0700243 *result = response.status == InterceptStatus::kStarted ? 1 : 0;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700244 }
245}
246
Josh Gao2e7b8e22017-05-04 17:12:57 -0700247void CrasherTest::StartProcess(std::function<void()> function, std::function<pid_t()> forker) {
Josh Gaofca7ca32017-01-23 12:05:35 -0800248 unique_fd read_pipe;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700249 unique_fd crasher_read_pipe;
250 if (!Pipe(&crasher_read_pipe, &crasher_pipe)) {
251 FAIL() << "failed to create pipe: " << strerror(errno);
252 }
253
Josh Gao2e7b8e22017-05-04 17:12:57 -0700254 crasher_pid = forker();
Josh Gaocbe70cb2016-10-18 18:17:52 -0700255 if (crasher_pid == -1) {
256 FAIL() << "fork failed: " << strerror(errno);
257 } else if (crasher_pid == 0) {
Josh Gao502cfd22017-02-17 01:39:15 -0800258 char dummy;
259 crasher_pipe.reset();
260 TEMP_FAILURE_RETRY(read(crasher_read_pipe.get(), &dummy, 1));
Josh Gaofca7ca32017-01-23 12:05:35 -0800261 function();
262 _exit(0);
263 }
264}
265
Josh Gaocbe70cb2016-10-18 18:17:52 -0700266void CrasherTest::FinishCrasher() {
267 if (crasher_pipe == -1) {
268 FAIL() << "crasher pipe uninitialized";
269 }
270
Christopher Ferris172b0a02019-09-18 17:48:30 -0700271 ssize_t rc = TEMP_FAILURE_RETRY(write(crasher_pipe.get(), "\n", 1));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700272 if (rc == -1) {
273 FAIL() << "failed to write to crasher pipe: " << strerror(errno);
274 } else if (rc == 0) {
275 FAIL() << "crasher pipe was closed";
276 }
277}
278
279void CrasherTest::AssertDeath(int signo) {
280 int status;
Christopher Ferris11555f02019-09-20 14:18:55 -0700281 pid_t pid = TIMEOUT(30, waitpid(crasher_pid, &status, 0));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700282 if (pid != crasher_pid) {
Christopher Ferrisafc0ff72019-06-26 15:08:51 -0700283 printf("failed to wait for crasher (expected pid %d, return value %d): %s\n", crasher_pid, pid,
284 strerror(errno));
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700285 sleep(100);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700286 FAIL() << "failed to wait for crasher: " << strerror(errno);
287 }
288
Josh Gaoe06f2a42017-04-27 16:50:38 -0700289 if (signo == 0) {
Christopher Ferris67022562021-04-16 13:30:32 -0700290 ASSERT_TRUE(WIFEXITED(status)) << "Terminated due to unexpected signal " << WTERMSIG(status);
Josh Gaoe06f2a42017-04-27 16:50:38 -0700291 ASSERT_EQ(0, WEXITSTATUS(signo));
292 } else {
293 ASSERT_FALSE(WIFEXITED(status));
294 ASSERT_TRUE(WIFSIGNALED(status)) << "crasher didn't terminate via a signal";
295 ASSERT_EQ(signo, WTERMSIG(status));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700296 }
Josh Gaocbe70cb2016-10-18 18:17:52 -0700297 crasher_pid = -1;
298}
299
300static void ConsumeFd(unique_fd fd, std::string* output) {
Kelvin Zhang786dac32023-06-15 16:23:56 -0700301 ASSERT_TRUE(android::base::ReadFdToString(fd, output));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700302}
303
Mitch Phillips78f06702021-06-01 14:35:43 -0700304class LogcatCollector {
305 public:
306 LogcatCollector() { system("logcat -c"); }
307
308 void Collect(std::string* output) {
309 FILE* cmd_stdout = popen("logcat -d '*:S DEBUG'", "r");
310 ASSERT_NE(cmd_stdout, nullptr);
311 unique_fd tmp_fd(TEMP_FAILURE_RETRY(dup(fileno(cmd_stdout))));
312 ConsumeFd(std::move(tmp_fd), output);
313 pclose(cmd_stdout);
314 }
315};
316
Josh Gaocbe70cb2016-10-18 18:17:52 -0700317TEST_F(CrasherTest, smoke) {
318 int intercept_result;
319 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -0800320 StartProcess([]() {
321 *reinterpret_cast<volatile char*>(0xdead) = '1';
322 });
323
Josh Gaocbe70cb2016-10-18 18:17:52 -0700324 StartIntercept(&output_fd);
325 FinishCrasher();
326 AssertDeath(SIGSEGV);
327 FinishIntercept(&intercept_result);
328
329 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
330
331 std::string result;
332 ConsumeFd(std::move(output_fd), &result);
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800333#ifdef __LP64__
334 ASSERT_MATCH(result,
335 R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x000000000000dead)");
336#else
337 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0000dead)");
338#endif
Peter Collingbourne864f15d2020-09-14 20:27:36 -0700339
340 if (mte_supported()) {
341 // Test that the default TAGGED_ADDR_CTRL value is set.
Peter Collingbourne47d784e2021-11-05 18:40:52 -0700342 ASSERT_MATCH(result, R"(tagged_addr_ctrl: 000000000007fff3)"
343 R"( \(PR_TAGGED_ADDR_ENABLE, PR_MTE_TCF_SYNC, mask 0xfffe\))");
Peter Collingbourne864f15d2020-09-14 20:27:36 -0700344 }
Elliott Hughesd13ea522022-01-13 09:20:26 -0800345
346 if (pac_supported()) {
347 // Test that the default PAC_ENABLED_KEYS value is set.
348 ASSERT_MATCH(result, R"(pac_enabled_keys: 000000000000000f)"
349 R"( \(PR_PAC_APIAKEY, PR_PAC_APIBKEY, PR_PAC_APDAKEY, PR_PAC_APDBKEY\))");
350 }
Josh Gaocbe70cb2016-10-18 18:17:52 -0700351}
352
Peter Collingbournef03af882020-03-20 18:09:00 -0700353TEST_F(CrasherTest, tagged_fault_addr) {
354#if !defined(__aarch64__)
355 GTEST_SKIP() << "Requires aarch64";
356#endif
Florian Mayerb4979292022-04-15 14:35:17 -0700357 // HWASan crashes with SIGABRT on tag mismatch.
358 SKIP_WITH_HWASAN;
Peter Collingbournef03af882020-03-20 18:09:00 -0700359 int intercept_result;
360 unique_fd output_fd;
361 StartProcess([]() {
362 *reinterpret_cast<volatile char*>(0x100000000000dead) = '1';
363 });
364
365 StartIntercept(&output_fd);
366 FinishCrasher();
367 AssertDeath(SIGSEGV);
368 FinishIntercept(&intercept_result);
369
370 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
371
372 std::string result;
373 ConsumeFd(std::move(output_fd), &result);
374
375 // The address can either be tagged (new kernels) or untagged (old kernels).
376 ASSERT_MATCH(
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800377 result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x[01]00000000000dead)");
Peter Collingbournef03af882020-03-20 18:09:00 -0700378}
379
Evgenii Stepanov361455e2022-10-13 16:23:08 -0700380void CrasherTest::Trap(void* ptr) {
381 void (*volatile f)(void*) = nullptr;
382 __asm__ __volatile__("" : : "r"(f) : "memory");
383 f(ptr);
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700384}
385
386TEST_F(CrasherTest, heap_addr_in_register) {
387#if defined(__i386__)
388 GTEST_SKIP() << "architecture does not pass arguments in registers";
389#endif
Florian Mayerb4979292022-04-15 14:35:17 -0700390 // The memory dump in HWASan crashes sadly shows the memory near the registers
391 // in the HWASan dump function, rather the faulting context. This is a known
392 // issue.
393 SKIP_WITH_HWASAN;
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700394 int intercept_result;
395 unique_fd output_fd;
396 StartProcess([]() {
397 // Crash with a heap pointer in the first argument register.
398 Trap(malloc(1));
399 });
400
401 StartIntercept(&output_fd);
402 FinishCrasher();
403 int status;
404 ASSERT_EQ(crasher_pid, TIMEOUT(30, waitpid(crasher_pid, &status, 0)));
405 ASSERT_TRUE(WIFSIGNALED(status)) << "crasher didn't terminate via a signal";
406 // Don't test the signal number because different architectures use different signals for
407 // __builtin_trap().
408 FinishIntercept(&intercept_result);
409
410 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
411
412 std::string result;
413 ConsumeFd(std::move(output_fd), &result);
414
415#if defined(__aarch64__)
Peter Collingbourne0ea08c22021-02-05 14:59:08 -0800416 ASSERT_MATCH(result, "memory near x0 \\(\\[anon:");
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700417#elif defined(__arm__)
Peter Collingbourne0ea08c22021-02-05 14:59:08 -0800418 ASSERT_MATCH(result, "memory near r0 \\(\\[anon:");
haocheng.zy@linux.alibaba.com3f4d0362022-09-10 11:38:19 +0800419#elif defined(__riscv)
420 ASSERT_MATCH(result, "memory near a0 \\(\\[anon:");
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700421#elif defined(__x86_64__)
Peter Collingbourne0ea08c22021-02-05 14:59:08 -0800422 ASSERT_MATCH(result, "memory near rdi \\(\\[anon:");
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700423#else
424 ASSERT_TRUE(false) << "unsupported architecture";
425#endif
426}
427
Peter Collingbournecd278072020-12-21 14:08:38 -0800428#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700429static void SetTagCheckingLevelSync() {
Elliott Hughes03b283a2021-01-15 11:34:26 -0800430 if (mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_SYNC) == 0) {
Peter Collingbournef8622522020-04-07 14:07:32 -0700431 abort();
432 }
433}
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800434
435static void SetTagCheckingLevelAsync() {
436 if (mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_ASYNC) == 0) {
437 abort();
438 }
439}
Peter Collingbournef8622522020-04-07 14:07:32 -0700440#endif
441
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800442struct SizeParamCrasherTest : CrasherTest, testing::WithParamInterface<size_t> {};
443
Peter Collingbourneaa544792021-05-13 13:53:37 -0700444INSTANTIATE_TEST_SUITE_P(Sizes, SizeParamCrasherTest, testing::Values(0, 16, 131072));
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800445
446TEST_P(SizeParamCrasherTest, mte_uaf) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800447#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700448 if (!mte_supported()) {
449 GTEST_SKIP() << "Requires MTE";
450 }
451
Peter Collingbourneaa544792021-05-13 13:53:37 -0700452 // Any UAF on a zero-sized allocation will be out-of-bounds so it won't be reported.
453 if (GetParam() == 0) {
454 return;
455 }
456
Mitch Phillips78f06702021-06-01 14:35:43 -0700457 LogcatCollector logcat_collector;
458
Peter Collingbournef8622522020-04-07 14:07:32 -0700459 int intercept_result;
460 unique_fd output_fd;
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800461 StartProcess([&]() {
Peter Collingbournef8622522020-04-07 14:07:32 -0700462 SetTagCheckingLevelSync();
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800463 volatile int* p = (volatile int*)malloc(GetParam());
Peter Collingbournef8622522020-04-07 14:07:32 -0700464 free((void *)p);
465 p[0] = 42;
466 });
467
468 StartIntercept(&output_fd);
469 FinishCrasher();
470 AssertDeath(SIGSEGV);
471 FinishIntercept(&intercept_result);
472
473 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
474
Mitch Phillips78f06702021-06-01 14:35:43 -0700475 std::vector<std::string> log_sources(2);
476 ConsumeFd(std::move(output_fd), &log_sources[0]);
477 logcat_collector.Collect(&log_sources[1]);
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700478 // Tag dump only available in the tombstone, not logcat.
479 ASSERT_MATCH(log_sources[0], "Memory tags around the fault address");
Peter Collingbournef8622522020-04-07 14:07:32 -0700480
Mitch Phillips78f06702021-06-01 14:35:43 -0700481 for (const auto& result : log_sources) {
482 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
483 ASSERT_MATCH(result, R"(Cause: \[MTE\]: Use After Free, 0 bytes into a )" +
484 std::to_string(GetParam()) + R"(-byte allocation)");
485 ASSERT_MATCH(result, R"(deallocated by thread .*?\n.*#00 pc)");
486 ASSERT_MATCH(result, R"((^|\s)allocated by thread .*?\n.*#00 pc)");
487 }
Peter Collingbournef8622522020-04-07 14:07:32 -0700488#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800489 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournef8622522020-04-07 14:07:32 -0700490#endif
491}
492
Peter Collingbournedc476342021-05-12 15:56:43 -0700493TEST_P(SizeParamCrasherTest, mte_oob_uaf) {
494#if defined(__aarch64__)
495 if (!mte_supported()) {
496 GTEST_SKIP() << "Requires MTE";
497 }
498
499 int intercept_result;
500 unique_fd output_fd;
501 StartProcess([&]() {
502 SetTagCheckingLevelSync();
503 volatile int* p = (volatile int*)malloc(GetParam());
504 free((void *)p);
505 p[-1] = 42;
506 });
507
508 StartIntercept(&output_fd);
509 FinishCrasher();
510 AssertDeath(SIGSEGV);
511 FinishIntercept(&intercept_result);
512
513 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
514
515 std::string result;
516 ConsumeFd(std::move(output_fd), &result);
517
518 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
519 ASSERT_NOT_MATCH(result, R"(Cause: \[MTE\]: Use After Free, 4 bytes left)");
520#else
521 GTEST_SKIP() << "Requires aarch64";
522#endif
523}
524
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800525TEST_P(SizeParamCrasherTest, mte_overflow) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800526#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700527 if (!mte_supported()) {
528 GTEST_SKIP() << "Requires MTE";
529 }
530
Mitch Phillips78f06702021-06-01 14:35:43 -0700531 LogcatCollector logcat_collector;
Peter Collingbournef8622522020-04-07 14:07:32 -0700532 int intercept_result;
533 unique_fd output_fd;
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800534 StartProcess([&]() {
Peter Collingbournef8622522020-04-07 14:07:32 -0700535 SetTagCheckingLevelSync();
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800536 volatile char* p = (volatile char*)malloc(GetParam());
537 p[GetParam()] = 42;
Peter Collingbournef8622522020-04-07 14:07:32 -0700538 });
539
540 StartIntercept(&output_fd);
541 FinishCrasher();
542 AssertDeath(SIGSEGV);
543 FinishIntercept(&intercept_result);
544
545 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
546
Mitch Phillips78f06702021-06-01 14:35:43 -0700547 std::vector<std::string> log_sources(2);
548 ConsumeFd(std::move(output_fd), &log_sources[0]);
549 logcat_collector.Collect(&log_sources[1]);
Peter Collingbournef8622522020-04-07 14:07:32 -0700550
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700551 // Tag dump only in tombstone, not logcat, and tagging is not used for
552 // overflow protection in the scudo secondary (guard pages are used instead).
553 if (GetParam() < 0x10000) {
554 ASSERT_MATCH(log_sources[0], "Memory tags around the fault address");
555 }
556
Mitch Phillips78f06702021-06-01 14:35:43 -0700557 for (const auto& result : log_sources) {
558 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
559 ASSERT_MATCH(result, R"(Cause: \[MTE\]: Buffer Overflow, 0 bytes right of a )" +
560 std::to_string(GetParam()) + R"(-byte allocation)");
561 ASSERT_MATCH(result, R"((^|\s)allocated by thread .*?\n.*#00 pc)");
562 }
Peter Collingbournef8622522020-04-07 14:07:32 -0700563#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800564 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournef8622522020-04-07 14:07:32 -0700565#endif
566}
567
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800568TEST_P(SizeParamCrasherTest, mte_underflow) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800569#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700570 if (!mte_supported()) {
571 GTEST_SKIP() << "Requires MTE";
572 }
573
574 int intercept_result;
575 unique_fd output_fd;
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800576 StartProcess([&]() {
Peter Collingbournef8622522020-04-07 14:07:32 -0700577 SetTagCheckingLevelSync();
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800578 volatile int* p = (volatile int*)malloc(GetParam());
Peter Collingbournef8622522020-04-07 14:07:32 -0700579 p[-1] = 42;
580 });
581
582 StartIntercept(&output_fd);
583 FinishCrasher();
584 AssertDeath(SIGSEGV);
585 FinishIntercept(&intercept_result);
586
587 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
588
589 std::string result;
590 ConsumeFd(std::move(output_fd), &result);
591
592 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 9 \(SEGV_MTESERR\))");
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800593 ASSERT_MATCH(result, R"(Cause: \[MTE\]: Buffer Underflow, 4 bytes left of a )" +
Peter Collingbourne1a1f7d72021-03-08 16:53:54 -0800594 std::to_string(GetParam()) + R"(-byte allocation)");
Mitch Phillips78f06702021-06-01 14:35:43 -0700595 ASSERT_MATCH(result, R"((^|\s)allocated by thread .*
Peter Collingbournebbe69052020-05-08 10:11:19 -0700596 #00 pc)");
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700597 ASSERT_MATCH(result, "Memory tags around the fault address");
Peter Collingbournef8622522020-04-07 14:07:32 -0700598#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800599 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournef8622522020-04-07 14:07:32 -0700600#endif
601}
602
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800603TEST_F(CrasherTest, mte_async) {
604#if defined(__aarch64__)
605 if (!mte_supported()) {
606 GTEST_SKIP() << "Requires MTE";
607 }
608
609 int intercept_result;
610 unique_fd output_fd;
611 StartProcess([&]() {
612 SetTagCheckingLevelAsync();
613 volatile int* p = (volatile int*)malloc(16);
614 p[-1] = 42;
615 });
616
617 StartIntercept(&output_fd);
618 FinishCrasher();
619 AssertDeath(SIGSEGV);
620 FinishIntercept(&intercept_result);
621
622 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
623
624 std::string result;
625 ConsumeFd(std::move(output_fd), &result);
626
Peter Collingbourne91e816a2023-03-07 21:24:47 -0800627 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code [89] \(SEGV_MTE[AS]ERR\), fault addr)");
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800628#else
629 GTEST_SKIP() << "Requires aarch64";
630#endif
631}
632
Peter Collingbournef8622522020-04-07 14:07:32 -0700633TEST_F(CrasherTest, mte_multiple_causes) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800634#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700635 if (!mte_supported()) {
636 GTEST_SKIP() << "Requires MTE";
637 }
638
Mitch Phillips78f06702021-06-01 14:35:43 -0700639 LogcatCollector logcat_collector;
640
Peter Collingbournef8622522020-04-07 14:07:32 -0700641 int intercept_result;
642 unique_fd output_fd;
643 StartProcess([]() {
644 SetTagCheckingLevelSync();
645
646 // Make two allocations with the same tag and close to one another. Check for both properties
647 // with a bounds check -- this relies on the fact that only if the allocations have the same tag
648 // would they be measured as closer than 128 bytes to each other. Otherwise they would be about
649 // (some non-zero value << 56) apart.
650 //
651 // The out-of-bounds access will be considered either an overflow of one or an underflow of the
652 // other.
653 std::set<uintptr_t> allocs;
654 for (int i = 0; i != 4096; ++i) {
655 uintptr_t alloc = reinterpret_cast<uintptr_t>(malloc(16));
656 auto it = allocs.insert(alloc).first;
657 if (it != allocs.begin() && *std::prev(it) + 128 > alloc) {
658 *reinterpret_cast<int*>(*std::prev(it) + 16) = 42;
659 }
660 if (std::next(it) != allocs.end() && alloc + 128 > *std::next(it)) {
661 *reinterpret_cast<int*>(alloc + 16) = 42;
662 }
663 }
664 });
665
666 StartIntercept(&output_fd);
667 FinishCrasher();
668 AssertDeath(SIGSEGV);
669 FinishIntercept(&intercept_result);
670
671 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
672
Mitch Phillips78f06702021-06-01 14:35:43 -0700673 std::vector<std::string> log_sources(2);
674 ConsumeFd(std::move(output_fd), &log_sources[0]);
675 logcat_collector.Collect(&log_sources[1]);
Peter Collingbournef8622522020-04-07 14:07:32 -0700676
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700677 // Tag dump only in the tombstone, not logcat.
678 ASSERT_MATCH(log_sources[0], "Memory tags around the fault address");
679
Mitch Phillips78f06702021-06-01 14:35:43 -0700680 for (const auto& result : log_sources) {
681 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
682 ASSERT_THAT(result, HasSubstr("Note: multiple potential causes for this crash were detected, "
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800683 "listing them in decreasing order of likelihood."));
Mitch Phillips78f06702021-06-01 14:35:43 -0700684 // Adjacent untracked allocations may cause us to see the wrong underflow here (or only
685 // overflows), so we can't match explicitly for an underflow message.
686 ASSERT_MATCH(result,
687 R"(Cause: \[MTE\]: Buffer Overflow, 0 bytes right of a 16-byte allocation)");
688 // Ensure there's at least two allocation traces (one for each cause).
689 ASSERT_MATCH(
690 result,
691 R"((^|\s)allocated by thread .*?\n.*#00 pc(.|\n)*?(^|\s)allocated by thread .*?\n.*#00 pc)");
692 }
Peter Collingbournef8622522020-04-07 14:07:32 -0700693#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800694 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournef8622522020-04-07 14:07:32 -0700695#endif
696}
697
Peter Collingbournecd278072020-12-21 14:08:38 -0800698#if defined(__aarch64__)
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700699static uintptr_t CreateTagMapping() {
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700700 // Some of the MTE tag dump tests assert that there is an inaccessible page to the left and right
701 // of the PROT_MTE page, so map three pages and set the two guard pages to PROT_NONE.
702 size_t page_size = getpagesize();
703 void* mapping = mmap(nullptr, page_size * 3, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
704 uintptr_t mapping_uptr = reinterpret_cast<uintptr_t>(mapping);
705 if (mapping == MAP_FAILED) {
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700706 return 0;
707 }
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700708 mprotect(reinterpret_cast<void*>(mapping_uptr + page_size), page_size,
709 PROT_READ | PROT_WRITE | PROT_MTE);
710 // Stripe the mapping, where even granules get tag '1', and odd granules get tag '0'.
711 for (uintptr_t offset = 0; offset < page_size; offset += 2 * kTagGranuleSize) {
712 uintptr_t tagged_addr = mapping_uptr + page_size + offset + (1ULL << 56);
713 __asm__ __volatile__(".arch_extension mte; stg %0, [%0]" : : "r"(tagged_addr) : "memory");
714 }
715 return mapping_uptr + page_size;
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700716}
717#endif
718
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700719TEST_F(CrasherTest, mte_register_tag_dump) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800720#if defined(__aarch64__)
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700721 if (!mte_supported()) {
722 GTEST_SKIP() << "Requires MTE";
723 }
724
725 int intercept_result;
726 unique_fd output_fd;
727 StartProcess([&]() {
728 SetTagCheckingLevelSync();
729 Trap(reinterpret_cast<void *>(CreateTagMapping()));
730 });
731
732 StartIntercept(&output_fd);
733 FinishCrasher();
Evgenii Stepanov361455e2022-10-13 16:23:08 -0700734 AssertDeath(SIGSEGV);
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700735 FinishIntercept(&intercept_result);
736
737 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
738
739 std::string result;
740 ConsumeFd(std::move(output_fd), &result);
741
742 ASSERT_MATCH(result, R"(memory near x0:
743.*
744.*
745 01.............0 0000000000000000 0000000000000000 ................
746 00.............0)");
747#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800748 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700749#endif
750}
751
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700752TEST_F(CrasherTest, mte_fault_tag_dump_front_truncated) {
753#if defined(__aarch64__)
754 if (!mte_supported()) {
755 GTEST_SKIP() << "Requires MTE";
756 }
757
758 int intercept_result;
759 unique_fd output_fd;
760 StartProcess([&]() {
761 SetTagCheckingLevelSync();
762 volatile char* p = reinterpret_cast<char*>(CreateTagMapping());
763 p[0] = 0; // Untagged pointer, tagged memory.
764 });
765
766 StartIntercept(&output_fd);
767 FinishCrasher();
768 AssertDeath(SIGSEGV);
769 FinishIntercept(&intercept_result);
770
771 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
772
773 std::string result;
774 ConsumeFd(std::move(output_fd), &result);
775
776 ASSERT_MATCH(result, R"(Memory tags around the fault address.*
777\s*=>0x[0-9a-f]+000:\[1\] 0 1 0)");
778#else
779 GTEST_SKIP() << "Requires aarch64";
780#endif
781}
782
783TEST_F(CrasherTest, mte_fault_tag_dump) {
784#if defined(__aarch64__)
785 if (!mte_supported()) {
786 GTEST_SKIP() << "Requires MTE";
787 }
788
789 int intercept_result;
790 unique_fd output_fd;
791 StartProcess([&]() {
792 SetTagCheckingLevelSync();
793 volatile char* p = reinterpret_cast<char*>(CreateTagMapping());
794 p[320] = 0; // Untagged pointer, tagged memory.
795 });
796
797 StartIntercept(&output_fd);
798 FinishCrasher();
799 AssertDeath(SIGSEGV);
800 FinishIntercept(&intercept_result);
801
802 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
803
804 std::string result;
805 ConsumeFd(std::move(output_fd), &result);
806
807 ASSERT_MATCH(result, R"(Memory tags around the fault address.*
808\s*0x[0-9a-f]+: 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
809\s*=>0x[0-9a-f]+: 1 0 1 0 \[1\] 0 1 0 1 0 1 0 1 0 1 0
810\s*0x[0-9a-f]+: 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
811)");
812#else
813 GTEST_SKIP() << "Requires aarch64";
814#endif
815}
816
817TEST_F(CrasherTest, mte_fault_tag_dump_rear_truncated) {
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 size_t page_size = getpagesize();
828 volatile char* p = reinterpret_cast<char*>(CreateTagMapping());
829 p[page_size - kTagGranuleSize * 2] = 0; // Untagged pointer, tagged memory.
830 });
831
832 StartIntercept(&output_fd);
833 FinishCrasher();
834 AssertDeath(SIGSEGV);
835 FinishIntercept(&intercept_result);
836
837 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
838
839 std::string result;
840 ConsumeFd(std::move(output_fd), &result);
841
842 ASSERT_MATCH(result, R"(Memory tags around the fault address)");
843 ASSERT_MATCH(result,
844 R"(\s*0x[0-9a-f]+: 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
845\s*=>0x[0-9a-f]+: 1 0 1 0 1 0 1 0 1 0 1 0 1 0 \[1\] 0
846
847)"); // Ensure truncation happened and there's a newline after the tag fault.
848#else
849 GTEST_SKIP() << "Requires aarch64";
850#endif
851}
852
Josh Gaocdea7502017-11-01 15:00:40 -0700853TEST_F(CrasherTest, LD_PRELOAD) {
854 int intercept_result;
855 unique_fd output_fd;
856 StartProcess([]() {
857 setenv("LD_PRELOAD", "nonexistent.so", 1);
858 *reinterpret_cast<volatile char*>(0xdead) = '1';
859 });
860
861 StartIntercept(&output_fd);
862 FinishCrasher();
863 AssertDeath(SIGSEGV);
864 FinishIntercept(&intercept_result);
865
866 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
867
868 std::string result;
869 ConsumeFd(std::move(output_fd), &result);
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800870 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+dead)");
Josh Gaocdea7502017-11-01 15:00:40 -0700871}
872
Josh Gaocbe70cb2016-10-18 18:17:52 -0700873TEST_F(CrasherTest, abort) {
874 int intercept_result;
875 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -0800876 StartProcess([]() {
877 abort();
878 });
Josh Gaocbe70cb2016-10-18 18:17:52 -0700879 StartIntercept(&output_fd);
880 FinishCrasher();
881 AssertDeath(SIGABRT);
882 FinishIntercept(&intercept_result);
883
884 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
885
886 std::string result;
887 ConsumeFd(std::move(output_fd), &result);
Andreas Gampe26cbafb2017-06-22 20:14:43 -0700888 ASSERT_BACKTRACE_FRAME(result, "abort");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700889}
890
891TEST_F(CrasherTest, signal) {
892 int intercept_result;
893 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -0800894 StartProcess([]() {
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700895 while (true) {
896 sleep(1);
897 }
Josh Gao502cfd22017-02-17 01:39:15 -0800898 });
Josh Gaocbe70cb2016-10-18 18:17:52 -0700899 StartIntercept(&output_fd);
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700900 FinishCrasher();
Josh Gaocbe70cb2016-10-18 18:17:52 -0700901 ASSERT_EQ(0, kill(crasher_pid, SIGSEGV));
902
903 AssertDeath(SIGSEGV);
904 FinishIntercept(&intercept_result);
905
906 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
907
908 std::string result;
909 ConsumeFd(std::move(output_fd), &result);
Elliott Hughes89722702018-05-02 10:47:00 -0700910 ASSERT_MATCH(
911 result,
912 R"(signal 11 \(SIGSEGV\), code 0 \(SI_USER from pid \d+, uid \d+\), fault addr --------)");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700913 ASSERT_MATCH(result, R"(backtrace:)");
914}
915
916TEST_F(CrasherTest, abort_message) {
917 int intercept_result;
918 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -0800919 StartProcess([]() {
Josh Gao1cc7bd82018-02-13 13:16:17 -0800920 // Arrived at experimentally;
921 // logd truncates at 4062.
922 // strlen("Abort message: ''") is 17.
923 // That's 4045, but we also want a NUL.
924 char buf[4045 + 1];
925 memset(buf, 'x', sizeof(buf));
926 buf[sizeof(buf) - 1] = '\0';
927 android_set_abort_message(buf);
Josh Gao502cfd22017-02-17 01:39:15 -0800928 abort();
929 });
Josh Gaocbe70cb2016-10-18 18:17:52 -0700930 StartIntercept(&output_fd);
931 FinishCrasher();
932 AssertDeath(SIGABRT);
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);
Josh Gao1cc7bd82018-02-13 13:16:17 -0800939 ASSERT_MATCH(result, R"(Abort message: 'x{4045}')");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700940}
941
Florian Mayer5fa66632024-02-07 16:42:23 -0800942static char g_crash_detail_value_changes[] = "crash_detail_value";
943static char g_crash_detail_value[] = "crash_detail_value";
944static char g_crash_detail_value2[] = "crash_detail_value2";
945
946inline crash_detail_t* _Nullable android_register_crash_detail_strs(const char* _Nonnull name,
947 const char* _Nonnull data) {
948 return android_register_crash_detail(name, strlen(name), data, strlen(data));
949}
950
951TEST_F(CrasherTest, crash_detail_single) {
952 int intercept_result;
953 unique_fd output_fd;
954 StartProcess([]() {
955 android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value);
956 abort();
957 });
958 StartIntercept(&output_fd);
959 FinishCrasher();
960 AssertDeath(SIGABRT);
961 FinishIntercept(&intercept_result);
962
963 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
964
965 std::string result;
966 ConsumeFd(std::move(output_fd), &result);
967 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'crash_detail_value')");
968}
969
970TEST_F(CrasherTest, crash_detail_single_byte_name) {
971 int intercept_result;
972 unique_fd output_fd;
973 StartProcess([]() {
974 android_register_crash_detail_strs("CRASH_DETAIL_NAME\1", g_crash_detail_value);
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_MATCH(result, R"(CRASH_DETAIL_NAME\\1: 'crash_detail_value')");
987}
988
989
990TEST_F(CrasherTest, crash_detail_single_bytes) {
991 int intercept_result;
992 unique_fd output_fd;
993 StartProcess([]() {
994 android_register_crash_detail("CRASH_DETAIL_NAME", strlen("CRASH_DETAIL_NAME"), "\1",
995 sizeof("\1"));
996 abort();
997 });
998 StartIntercept(&output_fd);
999 FinishCrasher();
1000 AssertDeath(SIGABRT);
1001 FinishIntercept(&intercept_result);
1002
1003 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1004
1005 std::string result;
1006 ConsumeFd(std::move(output_fd), &result);
1007 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: '\\1\\0')");
1008}
1009
1010TEST_F(CrasherTest, crash_detail_mixed) {
1011 int intercept_result;
1012 unique_fd output_fd;
1013 StartProcess([]() {
1014 const char data[] = "helloworld\1\255\3";
1015 android_register_crash_detail_strs("CRASH_DETAIL_NAME", data);
1016 abort();
1017 });
1018 StartIntercept(&output_fd);
1019 FinishCrasher();
1020 AssertDeath(SIGABRT);
1021 FinishIntercept(&intercept_result);
1022
1023 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1024
1025 std::string result;
1026 ConsumeFd(std::move(output_fd), &result);
1027 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'helloworld\\1\\255\\3')");
1028}
1029
1030TEST_F(CrasherTest, crash_detail_many) {
1031 int intercept_result;
1032 unique_fd output_fd;
1033 StartProcess([]() {
1034 for (int i = 0; i < 1000; ++i) {
1035 std::string name = "CRASH_DETAIL_NAME" + std::to_string(i);
1036 std::string value = "CRASH_DETAIL_VALUE" + std::to_string(i);
1037 auto* h = android_register_crash_detail_strs(name.data(), value.data());
1038 android_unregister_crash_detail(h);
1039 }
1040
1041 android_register_crash_detail_strs("FINAL_NAME", "FINAL_VALUE");
1042 android_register_crash_detail_strs("FINAL_NAME2", "FINAL_VALUE2");
1043 abort();
1044 });
1045 StartIntercept(&output_fd);
1046 FinishCrasher();
1047 AssertDeath(SIGABRT);
1048 FinishIntercept(&intercept_result);
1049
1050 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1051
1052 std::string result;
1053 ConsumeFd(std::move(output_fd), &result);
1054 ASSERT_NOT_MATCH(result, "CRASH_DETAIL_NAME");
1055 ASSERT_NOT_MATCH(result, "CRASH_DETAIL_VALUE");
1056 ASSERT_MATCH(result, R"(FINAL_NAME: 'FINAL_VALUE')");
1057 ASSERT_MATCH(result, R"(FINAL_NAME2: 'FINAL_VALUE2')");
1058}
1059
1060TEST_F(CrasherTest, crash_detail_single_changes) {
1061 int intercept_result;
1062 unique_fd output_fd;
1063 StartProcess([]() {
1064 android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value_changes);
1065 g_crash_detail_value_changes[0] = 'C';
1066 abort();
1067 });
1068 StartIntercept(&output_fd);
1069 FinishCrasher();
1070 AssertDeath(SIGABRT);
1071 FinishIntercept(&intercept_result);
1072
1073 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1074
1075 std::string result;
1076 ConsumeFd(std::move(output_fd), &result);
1077 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'Crash_detail_value')");
1078}
1079
1080TEST_F(CrasherTest, crash_detail_multiple) {
1081 int intercept_result;
1082 unique_fd output_fd;
1083 StartProcess([]() {
1084 android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value);
1085 android_register_crash_detail_strs("CRASH_DETAIL_NAME2", g_crash_detail_value2);
1086 abort();
1087 });
1088 StartIntercept(&output_fd);
1089 FinishCrasher();
1090 AssertDeath(SIGABRT);
1091 FinishIntercept(&intercept_result);
1092
1093 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1094
1095 std::string result;
1096 ConsumeFd(std::move(output_fd), &result);
1097 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'crash_detail_value')");
1098 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME2: 'crash_detail_value2')");
1099}
1100
1101TEST_F(CrasherTest, crash_detail_remove) {
1102 int intercept_result;
1103 unique_fd output_fd;
1104 StartProcess([]() {
1105 auto* detail1 = android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value);
1106 android_unregister_crash_detail(detail1);
1107 android_register_crash_detail_strs("CRASH_DETAIL_NAME2", g_crash_detail_value2);
1108 abort();
1109 });
1110 StartIntercept(&output_fd);
1111 FinishCrasher();
1112 AssertDeath(SIGABRT);
1113 FinishIntercept(&intercept_result);
1114
1115 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1116
1117 std::string result;
1118 ConsumeFd(std::move(output_fd), &result);
1119 ASSERT_NOT_MATCH(result, R"(CRASH_DETAIL_NAME: 'crash_detail_value')");
1120 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME2: 'crash_detail_value2')");
1121}
1122
Christopher Ferrise8891452021-08-17 17:34:53 -07001123TEST_F(CrasherTest, abort_message_newline_trimmed) {
1124 int intercept_result;
1125 unique_fd output_fd;
1126 StartProcess([]() {
1127 android_set_abort_message("Message with a newline.\n");
1128 abort();
1129 });
1130 StartIntercept(&output_fd);
1131 FinishCrasher();
1132 AssertDeath(SIGABRT);
1133 FinishIntercept(&intercept_result);
1134
1135 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1136
1137 std::string result;
1138 ConsumeFd(std::move(output_fd), &result);
1139 ASSERT_MATCH(result, R"(Abort message: 'Message with a newline.')");
1140}
1141
1142TEST_F(CrasherTest, abort_message_multiple_newlines_trimmed) {
1143 int intercept_result;
1144 unique_fd output_fd;
1145 StartProcess([]() {
1146 android_set_abort_message("Message with multiple newlines.\n\n\n\n\n");
1147 abort();
1148 });
1149 StartIntercept(&output_fd);
1150 FinishCrasher();
1151 AssertDeath(SIGABRT);
1152 FinishIntercept(&intercept_result);
1153
1154 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1155
1156 std::string result;
1157 ConsumeFd(std::move(output_fd), &result);
1158 ASSERT_MATCH(result, R"(Abort message: 'Message with multiple newlines.')");
1159}
1160
Josh Gaoe06f2a42017-04-27 16:50:38 -07001161TEST_F(CrasherTest, abort_message_backtrace) {
1162 int intercept_result;
1163 unique_fd output_fd;
1164 StartProcess([]() {
1165 android_set_abort_message("not actually aborting");
Josh Gaoa48b41b2019-12-13 14:11:04 -08001166 raise(BIONIC_SIGNAL_DEBUGGER);
Josh Gaoe06f2a42017-04-27 16:50:38 -07001167 exit(0);
1168 });
1169 StartIntercept(&output_fd);
1170 FinishCrasher();
1171 AssertDeath(0);
1172 FinishIntercept(&intercept_result);
1173
1174 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1175
1176 std::string result;
1177 ConsumeFd(std::move(output_fd), &result);
1178 ASSERT_NOT_MATCH(result, R"(Abort message:)");
1179}
1180
Josh Gaocbe70cb2016-10-18 18:17:52 -07001181TEST_F(CrasherTest, intercept_timeout) {
1182 int intercept_result;
1183 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -08001184 StartProcess([]() {
1185 abort();
1186 });
Josh Gaocbe70cb2016-10-18 18:17:52 -07001187 StartIntercept(&output_fd);
1188
1189 // Don't let crasher finish until we timeout.
1190 FinishIntercept(&intercept_result);
1191
1192 ASSERT_NE(1, intercept_result) << "tombstoned reported success? (intercept_result = "
1193 << intercept_result << ")";
1194
1195 FinishCrasher();
1196 AssertDeath(SIGABRT);
1197}
1198
Elliott Hughese4781d52021-03-17 09:15:15 -07001199TEST_F(CrasherTest, wait_for_debugger) {
1200 if (!android::base::SetProperty(kWaitForDebuggerKey, "1")) {
1201 FAIL() << "failed to enable wait_for_debugger";
Josh Gaocbe70cb2016-10-18 18:17:52 -07001202 }
1203 sleep(1);
1204
Josh Gao502cfd22017-02-17 01:39:15 -08001205 StartProcess([]() {
1206 abort();
1207 });
Josh Gaocbe70cb2016-10-18 18:17:52 -07001208 FinishCrasher();
1209
1210 int status;
Christopher Ferris172b0a02019-09-18 17:48:30 -07001211 ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, WUNTRACED)));
Josh Gaocbe70cb2016-10-18 18:17:52 -07001212 ASSERT_TRUE(WIFSTOPPED(status));
1213 ASSERT_EQ(SIGSTOP, WSTOPSIG(status));
1214
1215 ASSERT_EQ(0, kill(crasher_pid, SIGCONT));
1216
1217 AssertDeath(SIGABRT);
1218}
1219
Josh Gaocbe70cb2016-10-18 18:17:52 -07001220TEST_F(CrasherTest, backtrace) {
1221 std::string result;
1222 int intercept_result;
1223 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -08001224
1225 StartProcess([]() {
1226 abort();
1227 });
Narayan Kamatha73df602017-05-24 15:07:25 +01001228 StartIntercept(&output_fd, kDebuggerdNativeBacktrace);
Josh Gaocbe70cb2016-10-18 18:17:52 -07001229
1230 std::this_thread::sleep_for(500ms);
1231
1232 sigval val;
1233 val.sival_int = 1;
Josh Gaoa48b41b2019-12-13 14:11:04 -08001234 ASSERT_EQ(0, sigqueue(crasher_pid, BIONIC_SIGNAL_DEBUGGER, val)) << strerror(errno);
Josh Gaocbe70cb2016-10-18 18:17:52 -07001235 FinishIntercept(&intercept_result);
1236 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1237 ConsumeFd(std::move(output_fd), &result);
Jaesung Chung58778e12017-06-15 18:20:34 +09001238 ASSERT_BACKTRACE_FRAME(result, "read");
Josh Gaocbe70cb2016-10-18 18:17:52 -07001239
1240 int status;
1241 ASSERT_EQ(0, waitpid(crasher_pid, &status, WNOHANG | WUNTRACED));
1242
1243 StartIntercept(&output_fd);
1244 FinishCrasher();
1245 AssertDeath(SIGABRT);
1246 FinishIntercept(&intercept_result);
1247 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1248 ConsumeFd(std::move(output_fd), &result);
Andreas Gampe26cbafb2017-06-22 20:14:43 -07001249 ASSERT_BACKTRACE_FRAME(result, "abort");
Josh Gaocbe70cb2016-10-18 18:17:52 -07001250}
Josh Gaofca7ca32017-01-23 12:05:35 -08001251
1252TEST_F(CrasherTest, PR_SET_DUMPABLE_0_crash) {
Josh Gao502cfd22017-02-17 01:39:15 -08001253 int intercept_result;
1254 unique_fd output_fd;
Josh Gaofca7ca32017-01-23 12:05:35 -08001255 StartProcess([]() {
1256 prctl(PR_SET_DUMPABLE, 0);
Josh Gao502cfd22017-02-17 01:39:15 -08001257 abort();
Josh Gaofca7ca32017-01-23 12:05:35 -08001258 });
Josh Gao502cfd22017-02-17 01:39:15 -08001259
1260 StartIntercept(&output_fd);
1261 FinishCrasher();
1262 AssertDeath(SIGABRT);
1263 FinishIntercept(&intercept_result);
1264
1265 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1266
1267 std::string result;
1268 ConsumeFd(std::move(output_fd), &result);
Andreas Gampe26cbafb2017-06-22 20:14:43 -07001269 ASSERT_BACKTRACE_FRAME(result, "abort");
Josh Gaofca7ca32017-01-23 12:05:35 -08001270}
1271
Josh Gao502cfd22017-02-17 01:39:15 -08001272TEST_F(CrasherTest, capabilities) {
1273 ASSERT_EQ(0U, getuid()) << "capability test requires root";
1274
Josh Gaofca7ca32017-01-23 12:05:35 -08001275 StartProcess([]() {
Josh Gao502cfd22017-02-17 01:39:15 -08001276 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
1277 err(1, "failed to set PR_SET_KEEPCAPS");
1278 }
1279
1280 if (setresuid(1, 1, 1) != 0) {
1281 err(1, "setresuid failed");
1282 }
1283
1284 __user_cap_header_struct capheader;
1285 __user_cap_data_struct capdata[2];
1286 memset(&capheader, 0, sizeof(capheader));
1287 memset(&capdata, 0, sizeof(capdata));
1288
1289 capheader.version = _LINUX_CAPABILITY_VERSION_3;
1290 capheader.pid = 0;
1291
1292 // Turn on every third capability.
1293 static_assert(CAP_LAST_CAP > 33, "CAP_LAST_CAP <= 32");
1294 for (int i = 0; i < CAP_LAST_CAP; i += 3) {
1295 capdata[CAP_TO_INDEX(i)].permitted |= CAP_TO_MASK(i);
1296 capdata[CAP_TO_INDEX(i)].effective |= CAP_TO_MASK(i);
1297 }
1298
1299 // Make sure CAP_SYS_PTRACE is off.
1300 capdata[CAP_TO_INDEX(CAP_SYS_PTRACE)].permitted &= ~(CAP_TO_MASK(CAP_SYS_PTRACE));
1301 capdata[CAP_TO_INDEX(CAP_SYS_PTRACE)].effective &= ~(CAP_TO_MASK(CAP_SYS_PTRACE));
1302
1303 if (capset(&capheader, &capdata[0]) != 0) {
1304 err(1, "capset failed");
1305 }
1306
1307 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0) != 0) {
1308 err(1, "failed to drop ambient capabilities");
1309 }
1310
Josh Gaoa5199a92017-04-03 13:18:34 -07001311 pthread_setname_np(pthread_self(), "thread_name");
Josh Gao502cfd22017-02-17 01:39:15 -08001312 raise(SIGSYS);
Josh Gaofca7ca32017-01-23 12:05:35 -08001313 });
Josh Gao502cfd22017-02-17 01:39:15 -08001314
1315 unique_fd output_fd;
1316 StartIntercept(&output_fd);
1317 FinishCrasher();
1318 AssertDeath(SIGSYS);
1319
1320 std::string result;
1321 int intercept_result;
1322 FinishIntercept(&intercept_result);
1323 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1324 ConsumeFd(std::move(output_fd), &result);
Josh Gaoa5199a92017-04-03 13:18:34 -07001325 ASSERT_MATCH(result, R"(name: thread_name\s+>>> .+debuggerd_test(32|64) <<<)");
Jaesung Chung58778e12017-06-15 18:20:34 +09001326 ASSERT_BACKTRACE_FRAME(result, "tgkill");
Josh Gaofca7ca32017-01-23 12:05:35 -08001327}
Josh Gaoc3c8c022017-02-13 16:36:18 -08001328
Josh Gao2e7b8e22017-05-04 17:12:57 -07001329TEST_F(CrasherTest, fake_pid) {
1330 int intercept_result;
1331 unique_fd output_fd;
1332
1333 // Prime the getpid/gettid caches.
1334 UNUSED(getpid());
1335 UNUSED(gettid());
1336
1337 std::function<pid_t()> clone_fn = []() {
1338 return syscall(__NR_clone, SIGCHLD, nullptr, nullptr, nullptr, nullptr);
1339 };
1340 StartProcess(
1341 []() {
1342 ASSERT_NE(getpid(), syscall(__NR_getpid));
1343 ASSERT_NE(gettid(), syscall(__NR_gettid));
1344 raise(SIGSEGV);
1345 },
1346 clone_fn);
1347
1348 StartIntercept(&output_fd);
1349 FinishCrasher();
1350 AssertDeath(SIGSEGV);
1351 FinishIntercept(&intercept_result);
1352
1353 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1354
1355 std::string result;
1356 ConsumeFd(std::move(output_fd), &result);
Jaesung Chung58778e12017-06-15 18:20:34 +09001357 ASSERT_BACKTRACE_FRAME(result, "tgkill");
Josh Gao2e7b8e22017-05-04 17:12:57 -07001358}
1359
Josh Gaoe04ca272018-01-16 15:38:17 -08001360static const char* const kDebuggerdSeccompPolicy =
1361 "/system/etc/seccomp_policy/crash_dump." ABI_STRING ".policy";
1362
Mitch Phillips18ce5422023-01-19 14:23:49 -08001363static void setup_jail(minijail* jail) {
1364 if (!jail) {
1365 LOG(FATAL) << "failed to create minijail";
1366 }
1367
Josh Gao6f9eeec2018-09-12 13:55:47 -07001368 std::string policy;
1369 if (!android::base::ReadFileToString(kDebuggerdSeccompPolicy, &policy)) {
1370 PLOG(FATAL) << "failed to read policy file";
1371 }
1372
1373 // Allow a bunch of syscalls used by the tests.
1374 policy += "\nclone: 1";
1375 policy += "\nsigaltstack: 1";
1376 policy += "\nnanosleep: 1";
Christopher Ferrisab606682019-09-17 15:31:47 -07001377 policy += "\ngetrlimit: 1";
1378 policy += "\nugetrlimit: 1";
Josh Gao6f9eeec2018-09-12 13:55:47 -07001379
1380 FILE* tmp_file = tmpfile();
1381 if (!tmp_file) {
1382 PLOG(FATAL) << "tmpfile failed";
1383 }
1384
Christopher Ferris172b0a02019-09-18 17:48:30 -07001385 unique_fd tmp_fd(TEMP_FAILURE_RETRY(dup(fileno(tmp_file))));
Josh Gao6f9eeec2018-09-12 13:55:47 -07001386 if (!android::base::WriteStringToFd(policy, tmp_fd.get())) {
1387 PLOG(FATAL) << "failed to write policy to tmpfile";
1388 }
1389
1390 if (lseek(tmp_fd.get(), 0, SEEK_SET) != 0) {
1391 PLOG(FATAL) << "failed to seek tmp_fd";
Josh Gaoe04ca272018-01-16 15:38:17 -08001392 }
1393
Mitch Phillips18ce5422023-01-19 14:23:49 -08001394 minijail_no_new_privs(jail);
1395 minijail_log_seccomp_filter_failures(jail);
1396 minijail_use_seccomp_filter(jail);
1397 minijail_parse_seccomp_filters_from_fd(jail, tmp_fd.release());
1398}
Josh Gaoe04ca272018-01-16 15:38:17 -08001399
Mitch Phillips18ce5422023-01-19 14:23:49 -08001400static pid_t seccomp_fork_impl(void (*prejail)()) {
1401 ScopedMinijail jail{minijail_new()};
1402 setup_jail(jail.get());
Josh Gaoe04ca272018-01-16 15:38:17 -08001403
1404 pid_t result = fork();
1405 if (result == -1) {
1406 return result;
1407 } else if (result != 0) {
1408 return result;
1409 }
1410
1411 // Spawn and detach a thread that spins forever.
1412 std::atomic<bool> thread_ready(false);
1413 std::thread thread([&jail, &thread_ready]() {
1414 minijail_enter(jail.get());
1415 thread_ready = true;
1416 for (;;)
1417 ;
1418 });
1419 thread.detach();
1420
1421 while (!thread_ready) {
1422 continue;
1423 }
1424
Josh Gao70adac62018-02-22 11:38:33 -08001425 if (prejail) {
1426 prejail();
1427 }
1428
Josh Gaoe04ca272018-01-16 15:38:17 -08001429 minijail_enter(jail.get());
1430 return result;
1431}
1432
Josh Gao70adac62018-02-22 11:38:33 -08001433static pid_t seccomp_fork() {
1434 return seccomp_fork_impl(nullptr);
1435}
1436
Josh Gaoe04ca272018-01-16 15:38:17 -08001437TEST_F(CrasherTest, seccomp_crash) {
1438 int intercept_result;
1439 unique_fd output_fd;
1440
1441 StartProcess([]() { abort(); }, &seccomp_fork);
1442
1443 StartIntercept(&output_fd);
1444 FinishCrasher();
1445 AssertDeath(SIGABRT);
1446 FinishIntercept(&intercept_result);
1447 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1448
1449 std::string result;
1450 ConsumeFd(std::move(output_fd), &result);
1451 ASSERT_BACKTRACE_FRAME(result, "abort");
1452}
1453
Josh Gao70adac62018-02-22 11:38:33 -08001454static pid_t seccomp_fork_rlimit() {
1455 return seccomp_fork_impl([]() {
1456 struct rlimit rlim = {
1457 .rlim_cur = 512 * 1024 * 1024,
1458 .rlim_max = 512 * 1024 * 1024,
1459 };
1460
1461 if (setrlimit(RLIMIT_AS, &rlim) != 0) {
1462 raise(SIGINT);
1463 }
1464 });
1465}
1466
1467TEST_F(CrasherTest, seccomp_crash_oom) {
1468 int intercept_result;
1469 unique_fd output_fd;
1470
1471 StartProcess(
1472 []() {
1473 std::vector<void*> vec;
1474 for (int i = 0; i < 512; ++i) {
1475 char* buf = static_cast<char*>(malloc(1024 * 1024));
1476 if (!buf) {
1477 abort();
1478 }
1479 memset(buf, 0xff, 1024 * 1024);
1480 vec.push_back(buf);
1481 }
1482 },
1483 &seccomp_fork_rlimit);
1484
1485 StartIntercept(&output_fd);
1486 FinishCrasher();
1487 AssertDeath(SIGABRT);
1488 FinishIntercept(&intercept_result);
1489 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1490
1491 // We can't actually generate a backtrace, just make sure that the process terminates.
1492}
1493
Elliott Hughesb795d6f2022-09-14 20:15:19 +00001494__attribute__((__noinline__)) extern "C" bool raise_debugger_signal(DebuggerdDumpType dump_type) {
Josh Gaoe04ca272018-01-16 15:38:17 -08001495 siginfo_t siginfo;
1496 siginfo.si_code = SI_QUEUE;
1497 siginfo.si_pid = getpid();
1498 siginfo.si_uid = getuid();
1499
1500 if (dump_type != kDebuggerdNativeBacktrace && dump_type != kDebuggerdTombstone) {
1501 PLOG(FATAL) << "invalid dump type";
1502 }
1503
1504 siginfo.si_value.sival_int = dump_type == kDebuggerdNativeBacktrace;
1505
Josh Gaoa48b41b2019-12-13 14:11:04 -08001506 if (syscall(__NR_rt_tgsigqueueinfo, getpid(), gettid(), BIONIC_SIGNAL_DEBUGGER, &siginfo) != 0) {
Josh Gaoe04ca272018-01-16 15:38:17 -08001507 PLOG(ERROR) << "libdebuggerd_client: failed to send signal to self";
1508 return false;
1509 }
1510
1511 return true;
1512}
1513
Christopher Ferrisb999b822022-02-09 17:57:21 -08001514extern "C" void foo() {
1515 LOG(INFO) << "foo";
1516 std::this_thread::sleep_for(1s);
1517}
1518
1519extern "C" void bar() {
1520 LOG(INFO) << "bar";
1521 std::this_thread::sleep_for(1s);
1522}
1523
Josh Gaoe04ca272018-01-16 15:38:17 -08001524TEST_F(CrasherTest, seccomp_tombstone) {
1525 int intercept_result;
1526 unique_fd output_fd;
1527
1528 static const auto dump_type = kDebuggerdTombstone;
1529 StartProcess(
1530 []() {
Christopher Ferrisb999b822022-02-09 17:57:21 -08001531 std::thread a(foo);
1532 std::thread b(bar);
1533
1534 std::this_thread::sleep_for(100ms);
1535
Josh Gaoe04ca272018-01-16 15:38:17 -08001536 raise_debugger_signal(dump_type);
1537 _exit(0);
1538 },
1539 &seccomp_fork);
1540
1541 StartIntercept(&output_fd, dump_type);
1542 FinishCrasher();
1543 AssertDeath(0);
1544 FinishIntercept(&intercept_result);
1545 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1546
1547 std::string result;
1548 ConsumeFd(std::move(output_fd), &result);
1549 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
Christopher Ferrisb999b822022-02-09 17:57:21 -08001550 ASSERT_BACKTRACE_FRAME(result, "foo");
1551 ASSERT_BACKTRACE_FRAME(result, "bar");
Josh Gao6f9eeec2018-09-12 13:55:47 -07001552}
1553
Christopher Ferris303c6be2022-05-24 17:08:33 -07001554TEST_F(CrasherTest, seccomp_tombstone_thread_abort) {
1555 int intercept_result;
1556 unique_fd output_fd;
1557
1558 static const auto dump_type = kDebuggerdTombstone;
1559 StartProcess(
1560 []() {
1561 std::thread abort_thread([] { abort(); });
1562 abort_thread.join();
1563 },
1564 &seccomp_fork);
1565
1566 StartIntercept(&output_fd, dump_type);
1567 FinishCrasher();
1568 AssertDeath(SIGABRT);
1569 FinishIntercept(&intercept_result);
1570 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1571
1572 std::string result;
1573 ConsumeFd(std::move(output_fd), &result);
1574 ASSERT_BACKTRACE_FRAME(result, "abort");
1575}
1576
Christopher Ferris7c2e7e32022-05-27 12:57:58 -07001577TEST_F(CrasherTest, seccomp_tombstone_multiple_threads_abort) {
1578 int intercept_result;
1579 unique_fd output_fd;
1580
1581 static const auto dump_type = kDebuggerdTombstone;
1582 StartProcess(
1583 []() {
1584 std::thread a(foo);
1585 std::thread b(bar);
1586
1587 std::this_thread::sleep_for(100ms);
1588
1589 std::thread abort_thread([] { abort(); });
1590 abort_thread.join();
1591 },
1592 &seccomp_fork);
1593
1594 StartIntercept(&output_fd, dump_type);
1595 FinishCrasher();
1596 AssertDeath(SIGABRT);
1597 FinishIntercept(&intercept_result);
1598 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1599
1600 std::string result;
1601 ConsumeFd(std::move(output_fd), &result);
1602 ASSERT_BACKTRACE_FRAME(result, "abort");
1603 ASSERT_BACKTRACE_FRAME(result, "foo");
1604 ASSERT_BACKTRACE_FRAME(result, "bar");
1605 ASSERT_BACKTRACE_FRAME(result, "main");
1606}
1607
Josh Gaoe04ca272018-01-16 15:38:17 -08001608TEST_F(CrasherTest, seccomp_backtrace) {
1609 int intercept_result;
1610 unique_fd output_fd;
1611
1612 static const auto dump_type = kDebuggerdNativeBacktrace;
1613 StartProcess(
1614 []() {
Josh Gao6f9eeec2018-09-12 13:55:47 -07001615 std::thread a(foo);
1616 std::thread b(bar);
1617
1618 std::this_thread::sleep_for(100ms);
1619
Josh Gaoe04ca272018-01-16 15:38:17 -08001620 raise_debugger_signal(dump_type);
1621 _exit(0);
1622 },
1623 &seccomp_fork);
1624
1625 StartIntercept(&output_fd, dump_type);
1626 FinishCrasher();
1627 AssertDeath(0);
1628 FinishIntercept(&intercept_result);
1629 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1630
1631 std::string result;
1632 ConsumeFd(std::move(output_fd), &result);
1633 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
Josh Gao6f9eeec2018-09-12 13:55:47 -07001634 ASSERT_BACKTRACE_FRAME(result, "foo");
1635 ASSERT_BACKTRACE_FRAME(result, "bar");
Josh Gaoe04ca272018-01-16 15:38:17 -08001636}
1637
Christopher Ferris7c2e7e32022-05-27 12:57:58 -07001638TEST_F(CrasherTest, seccomp_backtrace_from_thread) {
1639 int intercept_result;
1640 unique_fd output_fd;
1641
1642 static const auto dump_type = kDebuggerdNativeBacktrace;
1643 StartProcess(
1644 []() {
1645 std::thread a(foo);
1646 std::thread b(bar);
1647
1648 std::this_thread::sleep_for(100ms);
1649
1650 std::thread raise_thread([] {
1651 raise_debugger_signal(dump_type);
1652 _exit(0);
1653 });
1654 raise_thread.join();
1655 },
1656 &seccomp_fork);
1657
1658 StartIntercept(&output_fd, dump_type);
1659 FinishCrasher();
1660 AssertDeath(0);
1661 FinishIntercept(&intercept_result);
1662 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1663
1664 std::string result;
1665 ConsumeFd(std::move(output_fd), &result);
1666 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
1667 ASSERT_BACKTRACE_FRAME(result, "foo");
1668 ASSERT_BACKTRACE_FRAME(result, "bar");
1669 ASSERT_BACKTRACE_FRAME(result, "main");
1670}
1671
Josh Gaoe04ca272018-01-16 15:38:17 -08001672TEST_F(CrasherTest, seccomp_crash_logcat) {
1673 StartProcess([]() { abort(); }, &seccomp_fork);
1674 FinishCrasher();
1675
1676 // Make sure we don't get SIGSYS when trying to dump a crash to logcat.
1677 AssertDeath(SIGABRT);
1678}
1679
Josh Gaofd13bf02017-08-18 15:37:26 -07001680TEST_F(CrasherTest, competing_tracer) {
1681 int intercept_result;
1682 unique_fd output_fd;
1683 StartProcess([]() {
Josh Gao2b2ae0c2017-08-21 14:31:17 -07001684 raise(SIGABRT);
Josh Gaofd13bf02017-08-18 15:37:26 -07001685 });
1686
1687 StartIntercept(&output_fd);
Josh Gaofd13bf02017-08-18 15:37:26 -07001688
1689 ASSERT_EQ(0, ptrace(PTRACE_SEIZE, crasher_pid, 0, 0));
Josh Gao2b2ae0c2017-08-21 14:31:17 -07001690 FinishCrasher();
Josh Gaofd13bf02017-08-18 15:37:26 -07001691
1692 int status;
Christopher Ferris172b0a02019-09-18 17:48:30 -07001693 ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
Josh Gaofd13bf02017-08-18 15:37:26 -07001694 ASSERT_TRUE(WIFSTOPPED(status));
1695 ASSERT_EQ(SIGABRT, WSTOPSIG(status));
1696
1697 ASSERT_EQ(0, ptrace(PTRACE_CONT, crasher_pid, 0, SIGABRT));
1698 FinishIntercept(&intercept_result);
1699 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1700
1701 std::string result;
1702 ConsumeFd(std::move(output_fd), &result);
1703 std::string regex = R"(failed to attach to thread \d+, already traced by )";
1704 regex += std::to_string(gettid());
1705 regex += R"( \(.+debuggerd_test)";
1706 ASSERT_MATCH(result, regex.c_str());
1707
Christopher Ferris172b0a02019-09-18 17:48:30 -07001708 ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
Josh Gao2b2ae0c2017-08-21 14:31:17 -07001709 ASSERT_TRUE(WIFSTOPPED(status));
1710 ASSERT_EQ(SIGABRT, WSTOPSIG(status));
1711
Josh Gaofd13bf02017-08-18 15:37:26 -07001712 ASSERT_EQ(0, ptrace(PTRACE_DETACH, crasher_pid, 0, SIGABRT));
1713 AssertDeath(SIGABRT);
1714}
1715
Mitch Phillips18ce5422023-01-19 14:23:49 -08001716struct GwpAsanTestParameters {
1717 size_t alloc_size;
1718 bool free_before_access;
1719 int access_offset;
1720 std::string cause_needle; // Needle to be found in the "Cause: [GWP-ASan]" line.
1721};
1722
1723struct GwpAsanCrasherTest
1724 : CrasherTest,
1725 testing::WithParamInterface<
1726 std::tuple<GwpAsanTestParameters, /* recoverable */ bool, /* seccomp */ bool>> {};
1727
1728GwpAsanTestParameters gwp_asan_tests[] = {
1729 {/* alloc_size */ 7, /* free_before_access */ true, /* access_offset */ 0,
1730 "Use After Free, 0 bytes into a 7-byte allocation"},
1731 {/* alloc_size */ 15, /* free_before_access */ true, /* access_offset */ 1,
1732 "Use After Free, 1 byte into a 15-byte allocation"},
1733 {/* alloc_size */ 4096, /* free_before_access */ false, /* access_offset */ 4098,
1734 "Buffer Overflow, 2 bytes right of a 4096-byte allocation"},
1735 {/* alloc_size */ 4096, /* free_before_access */ false, /* access_offset */ -1,
1736 "Buffer Underflow, 1 byte left of a 4096-byte allocation"},
1737};
1738
1739INSTANTIATE_TEST_SUITE_P(
1740 GwpAsanTests, GwpAsanCrasherTest,
1741 testing::Combine(testing::ValuesIn(gwp_asan_tests),
1742 /* recoverable */ testing::Bool(),
1743 /* seccomp */ testing::Bool()),
1744 [](const testing::TestParamInfo<
1745 std::tuple<GwpAsanTestParameters, /* recoverable */ bool, /* seccomp */ bool>>& info) {
1746 const GwpAsanTestParameters& params = std::get<0>(info.param);
1747 std::string name = params.free_before_access ? "UseAfterFree" : "Overflow";
1748 name += testing::PrintToString(params.alloc_size);
1749 name += "Alloc";
1750 if (params.access_offset < 0) {
1751 name += "Left";
1752 name += testing::PrintToString(params.access_offset * -1);
1753 } else {
1754 name += "Right";
1755 name += testing::PrintToString(params.access_offset);
1756 }
1757 name += "Bytes";
1758 if (std::get<1>(info.param)) name += "Recoverable";
1759 if (std::get<2>(info.param)) name += "Seccomp";
1760 return name;
1761 });
1762
1763TEST_P(GwpAsanCrasherTest, run_gwp_asan_test) {
1764 if (mte_supported()) {
1765 // Skip this test on MTE hardware, as MTE will reliably catch these errors
1766 // instead of GWP-ASan.
1767 GTEST_SKIP() << "Skipped on MTE.";
1768 }
1769 // Skip this test on HWASan, which will reliably catch test errors as well.
1770 SKIP_WITH_HWASAN;
1771
1772 GwpAsanTestParameters params = std::get<0>(GetParam());
1773 bool recoverable = std::get<1>(GetParam());
1774 LogcatCollector logcat_collector;
1775
1776 int intercept_result;
1777 unique_fd output_fd;
1778 StartProcess([&recoverable]() {
1779 const char* env[] = {"GWP_ASAN_SAMPLE_RATE=1", "GWP_ASAN_PROCESS_SAMPLING=1",
1780 "GWP_ASAN_MAX_ALLOCS=40000", nullptr, nullptr};
1781 if (recoverable) {
1782 env[3] = "GWP_ASAN_RECOVERABLE=true";
1783 }
1784 std::string test_name = ::testing::UnitTest::GetInstance()->current_test_info()->name();
1785 test_name = std::regex_replace(test_name, std::regex("run_gwp_asan_test"),
1786 "DISABLED_run_gwp_asan_test");
1787 std::string test_filter = "--gtest_filter=*";
1788 test_filter += test_name;
1789 std::string this_binary = android::base::GetExecutablePath();
1790 const char* args[] = {this_binary.c_str(), "--gtest_also_run_disabled_tests",
1791 test_filter.c_str(), nullptr};
1792 // We check the crash report from a debuggerd handler and from logcat. The
1793 // echo from stdout/stderr of the subprocess trips up atest, because it
1794 // doesn't like that two tests started in a row without the first one
1795 // finishing (even though the second one is in a subprocess).
1796 close(STDOUT_FILENO);
1797 close(STDERR_FILENO);
1798 execve(this_binary.c_str(), const_cast<char**>(args), const_cast<char**>(env));
1799 });
1800
1801 StartIntercept(&output_fd);
1802 FinishCrasher();
1803 if (recoverable) {
1804 AssertDeath(0);
1805 } else {
1806 AssertDeath(SIGSEGV);
1807 }
1808 FinishIntercept(&intercept_result);
1809
1810 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1811
1812 std::vector<std::string> log_sources(2);
1813 ConsumeFd(std::move(output_fd), &log_sources[0]);
1814 logcat_collector.Collect(&log_sources[1]);
1815
1816 // seccomp forces the fallback handler, which doesn't print GWP-ASan debugging
1817 // information. Make sure the recovery still works, but the report won't be
1818 // hugely useful, it looks like a regular SEGV.
1819 bool seccomp = std::get<2>(GetParam());
1820 if (!seccomp) {
1821 for (const auto& result : log_sources) {
1822 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\))");
1823 ASSERT_MATCH(result, R"(Cause: \[GWP-ASan\]: )" + params.cause_needle);
1824 if (params.free_before_access) {
1825 ASSERT_MATCH(result, R"(deallocated by thread .*\n.*#00 pc)");
1826 }
1827 ASSERT_MATCH(result, R"((^|\s)allocated by thread .*\n.*#00 pc)");
1828 }
1829 }
1830}
1831
1832TEST_P(GwpAsanCrasherTest, DISABLED_run_gwp_asan_test) {
1833 GwpAsanTestParameters params = std::get<0>(GetParam());
1834 bool seccomp = std::get<2>(GetParam());
1835 if (seccomp) {
1836 ScopedMinijail jail{minijail_new()};
1837 setup_jail(jail.get());
1838 minijail_enter(jail.get());
1839 }
1840
1841 // Use 'volatile' to prevent a very clever compiler eliminating the store.
1842 char* volatile p = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1843 if (params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
1844 p[params.access_offset] = 42;
1845 if (!params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
Mitch Phillips70aa2192023-02-22 11:31:36 -08001846
1847 bool recoverable = std::get<1>(GetParam());
1848 ASSERT_TRUE(recoverable); // Non-recoverable should have crashed.
1849
1850 // As we're in recoverable mode, trigger another 2x use-after-frees (ensuring
1851 // we end with at least one in a different slot), make sure the process still
1852 // doesn't crash.
1853 p = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1854 char* volatile p2 = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1855 free(static_cast<void*>(const_cast<char*>(p)));
1856 free(static_cast<void*>(const_cast<char*>(p2)));
1857 *p = 42;
1858 *p2 = 42;
1859
1860 // Under clang coverage (which is a default TEST_MAPPING presubmit target), the
1861 // recoverable+seccomp tests fail because the minijail prevents some atexit syscalls that clang
1862 // coverage does. Thus, skip the atexit handlers.
1863 _exit(0);
Mitch Phillips18ce5422023-01-19 14:23:49 -08001864}
1865
Josh Gaobf06a402018-08-27 16:34:01 -07001866TEST_F(CrasherTest, fdsan_warning_abort_message) {
1867 int intercept_result;
1868 unique_fd output_fd;
1869
1870 StartProcess([]() {
1871 android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
Christopher Ferris172b0a02019-09-18 17:48:30 -07001872 unique_fd fd(TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY | O_CLOEXEC)));
Josh Gaobf06a402018-08-27 16:34:01 -07001873 if (fd == -1) {
1874 abort();
1875 }
1876 close(fd.get());
1877 _exit(0);
1878 });
1879
1880 StartIntercept(&output_fd);
1881 FinishCrasher();
1882 AssertDeath(0);
1883 FinishIntercept(&intercept_result);
1884 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1885
1886 std::string result;
1887 ConsumeFd(std::move(output_fd), &result);
1888 ASSERT_MATCH(result, "Abort message: 'attempted to close");
1889}
1890
Josh Gaoc3c8c022017-02-13 16:36:18 -08001891TEST(crash_dump, zombie) {
1892 pid_t forkpid = fork();
1893
Josh Gaoc3c8c022017-02-13 16:36:18 -08001894 pid_t rc;
1895 int status;
1896
1897 if (forkpid == 0) {
1898 errno = 0;
1899 rc = waitpid(-1, &status, WNOHANG | __WALL | __WNOTHREAD);
1900 if (rc != -1 || errno != ECHILD) {
1901 errx(2, "first waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
1902 }
1903
Josh Gaoa48b41b2019-12-13 14:11:04 -08001904 raise(BIONIC_SIGNAL_DEBUGGER);
Josh Gaoc3c8c022017-02-13 16:36:18 -08001905
1906 errno = 0;
Christopher Ferris172b0a02019-09-18 17:48:30 -07001907 rc = TEMP_FAILURE_RETRY(waitpid(-1, &status, __WALL | __WNOTHREAD));
Josh Gaoc3c8c022017-02-13 16:36:18 -08001908 if (rc != -1 || errno != ECHILD) {
1909 errx(2, "second waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
1910 }
1911 _exit(0);
1912 } else {
Christopher Ferris172b0a02019-09-18 17:48:30 -07001913 rc = TEMP_FAILURE_RETRY(waitpid(forkpid, &status, 0));
Josh Gaoc3c8c022017-02-13 16:36:18 -08001914 ASSERT_EQ(forkpid, rc);
1915 ASSERT_TRUE(WIFEXITED(status));
1916 ASSERT_EQ(0, WEXITSTATUS(status));
1917 }
1918}
Josh Gao352a8452017-03-30 16:46:21 -07001919
1920TEST(tombstoned, no_notify) {
1921 // Do this a few times.
1922 for (int i = 0; i < 3; ++i) {
1923 pid_t pid = 123'456'789 + i;
1924
1925 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07001926 InterceptResponse response = {};
1927 tombstoned_intercept(pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
1928 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
1929 << "Error message: " << response.error_message;
Josh Gao352a8452017-03-30 16:46:21 -07001930
1931 {
1932 unique_fd tombstoned_socket, input_fd;
Narayan Kamatha73df602017-05-24 15:07:25 +01001933 ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
Josh Gao352a8452017-03-30 16:46:21 -07001934 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid)));
1935 }
1936
1937 pid_t read_pid;
1938 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid)));
1939 ASSERT_EQ(read_pid, pid);
1940 }
1941}
1942
1943TEST(tombstoned, stress) {
1944 // Spawn threads to simultaneously do a bunch of failing dumps and a bunch of successful dumps.
1945 static constexpr int kDumpCount = 100;
1946
1947 std::atomic<bool> start(false);
1948 std::vector<std::thread> threads;
1949 threads.emplace_back([&start]() {
1950 while (!start) {
1951 continue;
1952 }
1953
1954 // Use a way out of range pid, to avoid stomping on an actual process.
1955 pid_t pid_base = 1'000'000;
1956
1957 for (int dump = 0; dump < kDumpCount; ++dump) {
1958 pid_t pid = pid_base + dump;
1959
1960 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07001961 InterceptResponse response = {};
1962 tombstoned_intercept(pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
1963 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
1964 << "Error messeage: " << response.error_message;
Josh Gao352a8452017-03-30 16:46:21 -07001965
1966 // Pretend to crash, and then immediately close the socket.
1967 unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName,
1968 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
1969 if (sockfd == -1) {
1970 FAIL() << "failed to connect to tombstoned: " << strerror(errno);
1971 }
1972 TombstonedCrashPacket packet = {};
1973 packet.packet_type = CrashPacketType::kDumpRequest;
1974 packet.packet.dump_request.pid = pid;
1975 if (TEMP_FAILURE_RETRY(write(sockfd, &packet, sizeof(packet))) != sizeof(packet)) {
1976 FAIL() << "failed to write to tombstoned: " << strerror(errno);
1977 }
1978
1979 continue;
1980 }
1981 });
1982
1983 threads.emplace_back([&start]() {
1984 while (!start) {
1985 continue;
1986 }
1987
1988 // Use a way out of range pid, to avoid stomping on an actual process.
1989 pid_t pid_base = 2'000'000;
1990
1991 for (int dump = 0; dump < kDumpCount; ++dump) {
1992 pid_t pid = pid_base + dump;
1993
1994 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07001995 InterceptResponse response = {};
1996 tombstoned_intercept(pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
1997 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
1998 << "Error message: " << response.error_message;
Josh Gao352a8452017-03-30 16:46:21 -07001999
2000 {
2001 unique_fd tombstoned_socket, input_fd;
Narayan Kamatha73df602017-05-24 15:07:25 +01002002 ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
Josh Gao352a8452017-03-30 16:46:21 -07002003 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid)));
2004 tombstoned_notify_completion(tombstoned_socket.get());
2005 }
2006
2007 // TODO: Fix the race that requires this sleep.
2008 std::this_thread::sleep_for(50ms);
2009
2010 pid_t read_pid;
2011 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid)));
2012 ASSERT_EQ(read_pid, pid);
2013 }
2014 });
2015
2016 start = true;
2017
2018 for (std::thread& thread : threads) {
2019 thread.join();
2020 }
2021}
Narayan Kamathca5e9082017-06-02 15:42:06 +01002022
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002023TEST(tombstoned, intercept_java_trace_smoke) {
Narayan Kamathca5e9082017-06-02 15:42:06 +01002024 // Using a "real" PID is a little dangerous here - if the test fails
2025 // or crashes, we might end up getting a bogus / unreliable stack
2026 // trace.
2027 const pid_t self = getpid();
2028
2029 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002030 InterceptResponse response = {};
2031 tombstoned_intercept(self, &intercept_fd, &output_fd, &response, kDebuggerdJavaBacktrace);
2032 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2033 << "Error message: " << response.error_message;
Narayan Kamathca5e9082017-06-02 15:42:06 +01002034
Josh Gao76e1e302021-01-26 15:53:11 -08002035 // First connect to tombstoned requesting a native tombstone. This
Narayan Kamathca5e9082017-06-02 15:42:06 +01002036 // should result in a "regular" FD and not the installed intercept.
2037 const char native[] = "native";
2038 unique_fd tombstoned_socket, input_fd;
Josh Gao76e1e302021-01-26 15:53:11 -08002039 ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
Narayan Kamathca5e9082017-06-02 15:42:06 +01002040 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), native, sizeof(native)));
2041 tombstoned_notify_completion(tombstoned_socket.get());
2042
2043 // Then, connect to tombstoned asking for a java backtrace. This *should*
2044 // trigger the intercept.
2045 const char java[] = "java";
2046 ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdJavaBacktrace));
2047 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), java, sizeof(java)));
2048 tombstoned_notify_completion(tombstoned_socket.get());
2049
2050 char outbuf[sizeof(java)];
2051 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
2052 ASSERT_STREQ("java", outbuf);
2053}
2054
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002055TEST(tombstoned, intercept_multiple_dump_types) {
Narayan Kamathca5e9082017-06-02 15:42:06 +01002056 const pid_t fake_pid = 1'234'567;
2057 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002058 InterceptResponse response = {};
2059 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdJavaBacktrace);
2060 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2061 << "Error message: " << response.error_message;
Narayan Kamathca5e9082017-06-02 15:42:06 +01002062
2063 unique_fd intercept_fd_2, output_fd_2;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002064 tombstoned_intercept(fake_pid, &intercept_fd_2, &output_fd_2, &response,
2065 kDebuggerdNativeBacktrace);
2066 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2067 << "Error message: " << response.error_message;
2068}
2069
2070TEST(tombstoned, intercept_bad_pid) {
2071 const pid_t fake_pid = -1;
2072 unique_fd intercept_fd, output_fd;
2073 InterceptResponse response = {};
2074 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdNativeBacktrace);
2075 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2076 << "Error message: " << response.error_message;
2077 ASSERT_MATCH(response.error_message, "bad pid");
2078}
2079
2080TEST(tombstoned, intercept_bad_dump_types) {
2081 const pid_t fake_pid = 1'234'567;
2082 unique_fd intercept_fd, output_fd;
2083 InterceptResponse response = {};
2084 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response,
2085 static_cast<DebuggerdDumpType>(20));
2086 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2087 << "Error message: " << response.error_message;
2088 ASSERT_MATCH(response.error_message, "bad dump type \\[unknown\\]");
2089
2090 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdAnyIntercept);
2091 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2092 << "Error message: " << response.error_message;
2093 ASSERT_MATCH(response.error_message, "bad dump type kDebuggerdAnyIntercept");
2094
2095 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstoneProto);
2096 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2097 << "Error message: " << response.error_message;
2098 ASSERT_MATCH(response.error_message, "bad dump type kDebuggerdTombstoneProto");
2099}
2100
2101TEST(tombstoned, intercept_already_registered) {
2102 const pid_t fake_pid = 1'234'567;
2103 unique_fd intercept_fd1, output_fd1;
2104 InterceptResponse response = {};
2105 tombstoned_intercept(fake_pid, &intercept_fd1, &output_fd1, &response, kDebuggerdTombstone);
2106 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2107 << "Error message: " << response.error_message;
2108
2109 unique_fd intercept_fd2, output_fd2;
2110 tombstoned_intercept(fake_pid, &intercept_fd2, &output_fd2, &response, kDebuggerdTombstone);
2111 ASSERT_EQ(InterceptStatus::kFailedAlreadyRegistered, response.status)
2112 << "Error message: " << response.error_message;
2113 ASSERT_MATCH(response.error_message, "already registered, type kDebuggerdTombstone");
2114}
2115
2116TEST(tombstoned, intercept_tombstone_proto_matched_to_tombstone) {
2117 const pid_t fake_pid = 1'234'567;
2118
2119 unique_fd intercept_fd, output_fd;
2120 InterceptResponse response = {};
2121 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2122 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2123 << "Error message: " << response.error_message;
2124
2125 const char data[] = "tombstone_proto";
2126 unique_fd tombstoned_socket, input_fd;
2127 ASSERT_TRUE(
2128 tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdTombstoneProto));
2129 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), data, sizeof(data)));
2130 tombstoned_notify_completion(tombstoned_socket.get());
2131
2132 char outbuf[sizeof(data)];
2133 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
2134 ASSERT_STREQ("tombstone_proto", outbuf);
Narayan Kamathca5e9082017-06-02 15:42:06 +01002135}
2136
2137TEST(tombstoned, intercept_any) {
2138 const pid_t fake_pid = 1'234'567;
2139
2140 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002141 InterceptResponse response = {};
2142 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdNativeBacktrace);
2143 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2144 << "Error message: " << response.error_message;
Narayan Kamathca5e9082017-06-02 15:42:06 +01002145
2146 const char any[] = "any";
2147 unique_fd tombstoned_socket, input_fd;
2148 ASSERT_TRUE(tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdAnyIntercept));
2149 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), any, sizeof(any)));
2150 tombstoned_notify_completion(tombstoned_socket.get());
2151
2152 char outbuf[sizeof(any)];
2153 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
2154 ASSERT_STREQ("any", outbuf);
2155}
Josh Gao2b22ae12018-09-12 14:51:03 -07002156
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002157TEST(tombstoned, intercept_any_failed_with_multiple_intercepts) {
2158 const pid_t fake_pid = 1'234'567;
2159
2160 InterceptResponse response = {};
2161 unique_fd intercept_fd1, output_fd1;
2162 tombstoned_intercept(fake_pid, &intercept_fd1, &output_fd1, &response, kDebuggerdNativeBacktrace);
2163 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2164 << "Error message: " << response.error_message;
2165
2166 unique_fd intercept_fd2, output_fd2;
2167 tombstoned_intercept(fake_pid, &intercept_fd2, &output_fd2, &response, kDebuggerdJavaBacktrace);
2168 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2169 << "Error message: " << response.error_message;
2170
2171 unique_fd tombstoned_socket, input_fd;
2172 ASSERT_FALSE(tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdAnyIntercept));
2173}
2174
2175TEST(tombstoned, intercept_multiple_verify_intercept) {
2176 // Need to use our pid for java since that will verify the pid.
2177 const pid_t fake_pid = getpid();
2178
2179 InterceptResponse response = {};
2180 unique_fd intercept_fd1, output_fd1;
2181 tombstoned_intercept(fake_pid, &intercept_fd1, &output_fd1, &response, kDebuggerdNativeBacktrace);
2182 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2183 << "Error message: " << response.error_message;
2184
2185 unique_fd intercept_fd2, output_fd2;
2186 tombstoned_intercept(fake_pid, &intercept_fd2, &output_fd2, &response, kDebuggerdJavaBacktrace);
2187 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2188 << "Error message: " << response.error_message;
2189
2190 unique_fd intercept_fd3, output_fd3;
2191 tombstoned_intercept(fake_pid, &intercept_fd3, &output_fd3, &response, kDebuggerdTombstone);
2192 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2193 << "Error message: " << response.error_message;
2194
2195 const char native_data[] = "native";
2196 unique_fd tombstoned_socket1, input_fd1;
2197 ASSERT_TRUE(
2198 tombstoned_connect(fake_pid, &tombstoned_socket1, &input_fd1, kDebuggerdNativeBacktrace));
2199 ASSERT_TRUE(android::base::WriteFully(input_fd1.get(), native_data, sizeof(native_data)));
2200 tombstoned_notify_completion(tombstoned_socket1.get());
2201
2202 char native_outbuf[sizeof(native_data)];
2203 ASSERT_TRUE(android::base::ReadFully(output_fd1.get(), native_outbuf, sizeof(native_outbuf)));
2204 ASSERT_STREQ("native", native_outbuf);
2205
2206 const char java_data[] = "java";
2207 unique_fd tombstoned_socket2, input_fd2;
2208 ASSERT_TRUE(
2209 tombstoned_connect(fake_pid, &tombstoned_socket2, &input_fd2, kDebuggerdJavaBacktrace));
2210 ASSERT_TRUE(android::base::WriteFully(input_fd2.get(), java_data, sizeof(java_data)));
2211 tombstoned_notify_completion(tombstoned_socket2.get());
2212
2213 char java_outbuf[sizeof(java_data)];
2214 ASSERT_TRUE(android::base::ReadFully(output_fd2.get(), java_outbuf, sizeof(java_outbuf)));
2215 ASSERT_STREQ("java", java_outbuf);
2216
2217 const char tomb_data[] = "tombstone";
2218 unique_fd tombstoned_socket3, input_fd3;
2219 ASSERT_TRUE(tombstoned_connect(fake_pid, &tombstoned_socket3, &input_fd3, kDebuggerdTombstone));
2220 ASSERT_TRUE(android::base::WriteFully(input_fd3.get(), tomb_data, sizeof(tomb_data)));
2221 tombstoned_notify_completion(tombstoned_socket3.get());
2222
2223 char tomb_outbuf[sizeof(tomb_data)];
2224 ASSERT_TRUE(android::base::ReadFully(output_fd3.get(), tomb_outbuf, sizeof(tomb_outbuf)));
2225 ASSERT_STREQ("tombstone", tomb_outbuf);
2226}
2227
Josh Gao2b22ae12018-09-12 14:51:03 -07002228TEST(tombstoned, interceptless_backtrace) {
2229 // Generate 50 backtraces, and then check to see that we haven't created 50 new tombstones.
2230 auto get_tombstone_timestamps = []() -> std::map<int, time_t> {
2231 std::map<int, time_t> result;
2232 for (int i = 0; i < 99; ++i) {
2233 std::string path = android::base::StringPrintf("/data/tombstones/tombstone_%02d", i);
2234 struct stat st;
2235 if (stat(path.c_str(), &st) == 0) {
2236 result[i] = st.st_mtim.tv_sec;
2237 }
2238 }
2239 return result;
2240 };
2241
2242 auto before = get_tombstone_timestamps();
2243 for (int i = 0; i < 50; ++i) {
2244 raise_debugger_signal(kDebuggerdNativeBacktrace);
2245 }
2246 auto after = get_tombstone_timestamps();
2247
2248 int diff = 0;
2249 for (int i = 0; i < 99; ++i) {
2250 if (after.count(i) == 0) {
2251 continue;
2252 }
2253 if (before.count(i) == 0) {
2254 ++diff;
2255 continue;
2256 }
2257 if (before[i] != after[i]) {
2258 ++diff;
2259 }
2260 }
2261
2262 // We can't be sure that nothing's crash looping in the background.
2263 // This should be good enough, though...
2264 ASSERT_LT(diff, 10) << "too many new tombstones; is something crashing in the background?";
2265}
Christopher Ferris481e8372019-07-15 17:13:24 -07002266
2267static __attribute__((__noinline__)) void overflow_stack(void* p) {
2268 void* buf[1];
2269 buf[0] = p;
2270 static volatile void* global = buf;
2271 if (global) {
2272 global = buf;
2273 overflow_stack(&buf);
2274 }
2275}
2276
2277TEST_F(CrasherTest, stack_overflow) {
2278 int intercept_result;
2279 unique_fd output_fd;
2280 StartProcess([]() { overflow_stack(nullptr); });
2281
2282 StartIntercept(&output_fd);
2283 FinishCrasher();
2284 AssertDeath(SIGSEGV);
2285 FinishIntercept(&intercept_result);
2286
2287 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2288
2289 std::string result;
2290 ConsumeFd(std::move(output_fd), &result);
2291 ASSERT_MATCH(result, R"(Cause: stack pointer[^\n]*stack overflow.\n)");
2292}
Josh Gao76e1e302021-01-26 15:53:11 -08002293
Christopher Ferris22035cc2023-01-31 17:50:22 -08002294static std::string GetTestLibraryPath() {
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002295 std::string test_lib(testing::internal::GetArgvs()[0]);
2296 auto const value = test_lib.find_last_of('/');
2297 if (value == std::string::npos) {
2298 test_lib = "./";
2299 } else {
2300 test_lib = test_lib.substr(0, value + 1) + "./";
2301 }
Christopher Ferris22035cc2023-01-31 17:50:22 -08002302 return test_lib + "libcrash_test.so";
2303}
2304
2305static void CreateEmbeddedLibrary(int out_fd) {
2306 std::string test_lib(GetTestLibraryPath());
2307 android::base::unique_fd fd(open(test_lib.c_str(), O_RDONLY | O_CLOEXEC));
2308 ASSERT_NE(fd.get(), -1);
2309 off_t file_size = lseek(fd, 0, SEEK_END);
2310 ASSERT_EQ(lseek(fd, 0, SEEK_SET), 0);
2311 std::vector<uint8_t> contents(file_size);
2312 ASSERT_TRUE(android::base::ReadFully(fd, contents.data(), contents.size()));
2313
2314 // Put the shared library data at a pagesize() offset.
2315 ASSERT_EQ(lseek(out_fd, 4 * getpagesize(), SEEK_CUR), 4 * getpagesize());
2316 ASSERT_EQ(static_cast<size_t>(write(out_fd, contents.data(), contents.size())), contents.size());
2317}
2318
2319TEST_F(CrasherTest, non_zero_offset_in_library) {
2320 int intercept_result;
2321 unique_fd output_fd;
2322 TemporaryFile tf;
2323 CreateEmbeddedLibrary(tf.fd);
2324 StartProcess([&tf]() {
2325 android_dlextinfo extinfo{};
2326 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
2327 extinfo.library_fd = tf.fd;
2328 extinfo.library_fd_offset = 4 * getpagesize();
2329 void* handle = android_dlopen_ext(tf.path, RTLD_NOW, &extinfo);
2330 if (handle == nullptr) {
2331 _exit(1);
2332 }
2333 void (*crash_func)() = reinterpret_cast<void (*)()>(dlsym(handle, "crash"));
2334 if (crash_func == nullptr) {
2335 _exit(1);
2336 }
2337 crash_func();
2338 });
2339
2340 StartIntercept(&output_fd);
2341 FinishCrasher();
2342 AssertDeath(SIGSEGV);
2343 FinishIntercept(&intercept_result);
2344
2345 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2346
2347 std::string result;
2348 ConsumeFd(std::move(output_fd), &result);
2349
2350 // Verify the crash includes an offset value in the backtrace.
2351 std::string match_str = android::base::StringPrintf("%s\\!libcrash_test.so \\(offset 0x%x\\)",
2352 tf.path, 4 * getpagesize());
2353 ASSERT_MATCH(result, match_str);
2354}
2355
2356static bool CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) {
2357 std::string test_lib(GetTestLibraryPath());
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002358
2359 *tmp_so_name = std::string(tmp_dir) + "/libcrash_test.so";
2360 std::string cp_cmd = android::base::StringPrintf("cp %s %s", test_lib.c_str(), tmp_dir);
2361
2362 // Copy the shared so to a tempory directory.
2363 return system(cp_cmd.c_str()) == 0;
2364}
2365
2366TEST_F(CrasherTest, unreadable_elf) {
2367 int intercept_result;
2368 unique_fd output_fd;
Christopher Ferrisc95047d2022-03-14 15:02:11 -07002369 std::string tmp_so_name;
2370 StartProcess([&tmp_so_name]() {
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002371 TemporaryDir td;
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002372 if (!CopySharedLibrary(td.path, &tmp_so_name)) {
2373 _exit(1);
2374 }
2375 void* handle = dlopen(tmp_so_name.c_str(), RTLD_NOW);
2376 if (handle == nullptr) {
2377 _exit(1);
2378 }
2379 // Delete the original shared library so that we get the warning
2380 // about unreadable elf files.
2381 if (unlink(tmp_so_name.c_str()) == -1) {
2382 _exit(1);
2383 }
2384 void (*crash_func)() = reinterpret_cast<void (*)()>(dlsym(handle, "crash"));
2385 if (crash_func == nullptr) {
2386 _exit(1);
2387 }
2388 crash_func();
2389 });
2390
2391 StartIntercept(&output_fd);
2392 FinishCrasher();
2393 AssertDeath(SIGSEGV);
2394 FinishIntercept(&intercept_result);
2395
2396 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2397
2398 std::string result;
2399 ConsumeFd(std::move(output_fd), &result);
2400 ASSERT_MATCH(result, R"(NOTE: Function names and BuildId information is missing )");
Christopher Ferrisc95047d2022-03-14 15:02:11 -07002401 std::string match_str = "NOTE: " + tmp_so_name;
2402 ASSERT_MATCH(result, match_str);
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002403}
2404
Christopher Ferris20f50ec2024-01-03 02:30:03 +00002405void CheckForTombstone(const struct stat& text_st, std::optional<std::string>& tombstone_file) {
2406 static std::regex tombstone_re("tombstone_\\d+");
Christopher Ferris35da2882021-02-17 15:39:06 -08002407 std::unique_ptr<DIR, decltype(&closedir)> dir_h(opendir("/data/tombstones"), closedir);
2408 ASSERT_TRUE(dir_h != nullptr);
Christopher Ferris35da2882021-02-17 15:39:06 -08002409 dirent* entry;
2410 while ((entry = readdir(dir_h.get())) != nullptr) {
2411 if (!std::regex_match(entry->d_name, tombstone_re)) {
2412 continue;
2413 }
2414 std::string path = android::base::StringPrintf("/data/tombstones/%s", entry->d_name);
Josh Gao76e1e302021-01-26 15:53:11 -08002415
2416 struct stat st;
2417 if (TEMP_FAILURE_RETRY(stat(path.c_str(), &st)) != 0) {
2418 continue;
2419 }
2420
2421 if (st.st_dev == text_st.st_dev && st.st_ino == text_st.st_ino) {
Christopher Ferris35da2882021-02-17 15:39:06 -08002422 tombstone_file = path;
Josh Gao76e1e302021-01-26 15:53:11 -08002423 break;
2424 }
2425 }
Christopher Ferris20f50ec2024-01-03 02:30:03 +00002426}
Josh Gao76e1e302021-01-26 15:53:11 -08002427
Christopher Ferris20f50ec2024-01-03 02:30:03 +00002428TEST(tombstoned, proto) {
2429 const pid_t self = getpid();
2430 unique_fd tombstoned_socket, text_fd, proto_fd;
2431 ASSERT_TRUE(
2432 tombstoned_connect(self, &tombstoned_socket, &text_fd, &proto_fd, kDebuggerdTombstoneProto));
2433
2434 tombstoned_notify_completion(tombstoned_socket.get());
2435
2436 ASSERT_NE(-1, text_fd.get());
2437 ASSERT_NE(-1, proto_fd.get());
2438
2439 struct stat text_st;
2440 ASSERT_EQ(0, fstat(text_fd.get(), &text_st));
2441
2442 std::optional<std::string> tombstone_file;
2443 // Allow up to 5 seconds for the tombstone to be written to the system.
2444 const auto max_wait_time = std::chrono::seconds(5) * android::base::HwTimeoutMultiplier();
2445 const auto start = std::chrono::high_resolution_clock::now();
2446 while (true) {
2447 std::this_thread::sleep_for(100ms);
2448 CheckForTombstone(text_st, tombstone_file);
2449 if (tombstone_file) {
2450 break;
2451 }
2452 if (std::chrono::high_resolution_clock::now() - start > max_wait_time) {
2453 break;
2454 }
2455 }
2456
2457 ASSERT_TRUE(tombstone_file) << "Timed out trying to find tombstone file.";
Christopher Ferris35da2882021-02-17 15:39:06 -08002458 std::string proto_path = tombstone_file.value() + ".pb";
Josh Gao76e1e302021-01-26 15:53:11 -08002459
2460 struct stat proto_fd_st;
2461 struct stat proto_file_st;
2462 ASSERT_EQ(0, fstat(proto_fd.get(), &proto_fd_st));
2463 ASSERT_EQ(0, stat(proto_path.c_str(), &proto_file_st));
2464
2465 ASSERT_EQ(proto_fd_st.st_dev, proto_file_st.st_dev);
2466 ASSERT_EQ(proto_fd_st.st_ino, proto_file_st.st_ino);
2467}
2468
2469TEST(tombstoned, proto_intercept) {
2470 const pid_t self = getpid();
2471 unique_fd intercept_fd, output_fd;
Josh Gao76e1e302021-01-26 15:53:11 -08002472
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002473 InterceptResponse response = {};
2474 tombstoned_intercept(self, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2475 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2476 << "Error message: " << response.error_message;
Josh Gao76e1e302021-01-26 15:53:11 -08002477
2478 unique_fd tombstoned_socket, text_fd, proto_fd;
2479 ASSERT_TRUE(
2480 tombstoned_connect(self, &tombstoned_socket, &text_fd, &proto_fd, kDebuggerdTombstoneProto));
2481 ASSERT_TRUE(android::base::WriteStringToFd("foo", text_fd.get()));
2482 tombstoned_notify_completion(tombstoned_socket.get());
2483
2484 text_fd.reset();
2485
2486 std::string output;
2487 ASSERT_TRUE(android::base::ReadFdToString(output_fd, &output));
2488 ASSERT_EQ("foo", output);
2489}
Christopher Ferrisa3e9a0b2021-07-29 12:38:07 -07002490
2491// Verify that when an intercept is present for the main thread, and the signal
2492// is received on a different thread, the intercept still works.
2493TEST_F(CrasherTest, intercept_for_main_thread_signal_on_side_thread) {
2494 StartProcess([]() {
2495 std::thread thread([]() {
2496 // Raise the signal on the side thread.
2497 raise_debugger_signal(kDebuggerdNativeBacktrace);
2498 });
2499 thread.join();
2500 _exit(0);
2501 });
2502
2503 unique_fd output_fd;
2504 StartIntercept(&output_fd, kDebuggerdNativeBacktrace);
2505 FinishCrasher();
2506 AssertDeath(0);
2507
2508 int intercept_result;
2509 FinishIntercept(&intercept_result);
2510 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2511
2512 std::string result;
2513 ConsumeFd(std::move(output_fd), &result);
2514 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
2515}
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002516
2517static std::string format_pointer(uintptr_t ptr) {
2518#if defined(__LP64__)
2519 return android::base::StringPrintf("%08x'%08x", static_cast<uint32_t>(ptr >> 32),
2520 static_cast<uint32_t>(ptr & 0xffffffff));
2521#else
2522 return android::base::StringPrintf("%08x", static_cast<uint32_t>(ptr & 0xffffffff));
2523#endif
2524}
2525
2526static std::string format_pointer(void* ptr) {
2527 return format_pointer(reinterpret_cast<uintptr_t>(ptr));
2528}
2529
2530static std::string format_full_pointer(uintptr_t ptr) {
2531#if defined(__LP64__)
2532 return android::base::StringPrintf("%016" PRIx64, ptr);
2533#else
2534 return android::base::StringPrintf("%08x", ptr);
2535#endif
2536}
2537
2538static std::string format_full_pointer(void* ptr) {
2539 return format_full_pointer(reinterpret_cast<uintptr_t>(ptr));
2540}
2541
2542__attribute__((__noinline__)) int crash_call(uintptr_t ptr) {
2543 int* crash_ptr = reinterpret_cast<int*>(ptr);
2544 *crash_ptr = 1;
2545 return *crash_ptr;
2546}
2547
2548// Verify that a fault address before the first map is properly handled.
2549TEST_F(CrasherTest, fault_address_before_first_map) {
2550 StartProcess([]() {
2551 ASSERT_EQ(0, crash_call(0x1024));
2552 _exit(0);
2553 });
2554
2555 unique_fd output_fd;
2556 StartIntercept(&output_fd);
2557 FinishCrasher();
2558 AssertDeath(SIGSEGV);
2559
2560 int intercept_result;
2561 FinishIntercept(&intercept_result);
2562 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2563
2564 std::string result;
2565 ConsumeFd(std::move(output_fd), &result);
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002566 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+1024)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002567
2568 ASSERT_MATCH(result, R"(\nmemory map \(.*\):\n)");
2569
2570 std::string match_str = android::base::StringPrintf(
2571 R"(memory map .*:\n--->Fault address falls at %s before any mapped regions\n )",
2572 format_pointer(0x1024).c_str());
2573 ASSERT_MATCH(result, match_str);
2574}
2575
2576// Verify that a fault address after the last map is properly handled.
2577TEST_F(CrasherTest, fault_address_after_last_map) {
Florian Mayerb4979292022-04-15 14:35:17 -07002578 // This makes assumptions about the memory layout that are not true in HWASan
2579 // processes.
2580 SKIP_WITH_HWASAN;
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002581 uintptr_t crash_uptr = untag_address(UINTPTR_MAX - 15);
2582 StartProcess([crash_uptr]() {
2583 ASSERT_EQ(0, crash_call(crash_uptr));
2584 _exit(0);
2585 });
2586
2587 unique_fd output_fd;
2588 StartIntercept(&output_fd);
2589 FinishCrasher();
2590 AssertDeath(SIGSEGV);
2591
2592 int intercept_result;
2593 FinishIntercept(&intercept_result);
2594 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2595
2596 std::string result;
2597 ConsumeFd(std::move(output_fd), &result);
2598
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002599 std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x)";
2600 match_str += format_full_pointer(crash_uptr);
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002601 ASSERT_MATCH(result, match_str);
2602
2603 ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
2604
Christopher Ferris3a0833c2023-07-28 13:07:53 -07002605 // Verifies that the fault address error message is at the end of the
2606 // maps section. To do this, the check below looks for the start of the
2607 // open files section or the start of the log file section. It's possible
2608 // for either of these sections to be present after the maps section right
2609 // now.
2610 // If the sections move around, this check might need to be modified.
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002611 match_str = android::base::StringPrintf(
Christopher Ferris3a0833c2023-07-28 13:07:53 -07002612 R"(\n--->Fault address falls at %s after any mapped regions\n(---------|\nopen files:))",
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002613 format_pointer(crash_uptr).c_str());
2614 ASSERT_MATCH(result, match_str);
2615}
2616
2617// Verify that a fault address between maps is properly handled.
2618TEST_F(CrasherTest, fault_address_between_maps) {
2619 // Create a map before the fork so it will be present in the child.
2620 void* start_ptr =
2621 mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2622 ASSERT_NE(MAP_FAILED, start_ptr);
2623 // Unmap the page in the middle.
2624 void* middle_ptr =
2625 reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start_ptr) + getpagesize());
2626 ASSERT_EQ(0, munmap(middle_ptr, getpagesize()));
2627
2628 StartProcess([middle_ptr]() {
2629 ASSERT_EQ(0, crash_call(reinterpret_cast<uintptr_t>(middle_ptr)));
2630 _exit(0);
2631 });
2632
2633 // Unmap the two maps.
2634 ASSERT_EQ(0, munmap(start_ptr, getpagesize()));
2635 void* end_ptr =
2636 reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start_ptr) + 2 * getpagesize());
2637 ASSERT_EQ(0, munmap(end_ptr, getpagesize()));
2638
2639 unique_fd output_fd;
2640 StartIntercept(&output_fd);
2641 FinishCrasher();
2642 AssertDeath(SIGSEGV);
2643
2644 int intercept_result;
2645 FinishIntercept(&intercept_result);
2646 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2647
2648 std::string result;
2649 ConsumeFd(std::move(output_fd), &result);
2650
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002651 std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x)";
2652 match_str += format_full_pointer(reinterpret_cast<uintptr_t>(middle_ptr));
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002653 ASSERT_MATCH(result, match_str);
2654
2655 ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
2656
2657 match_str = android::base::StringPrintf(
2658 R"( %s.*\n--->Fault address falls at %s between mapped regions\n %s)",
2659 format_pointer(start_ptr).c_str(), format_pointer(middle_ptr).c_str(),
2660 format_pointer(end_ptr).c_str());
2661 ASSERT_MATCH(result, match_str);
2662}
2663
2664// Verify that a fault address happens in the correct map.
2665TEST_F(CrasherTest, fault_address_in_map) {
2666 // Create a map before the fork so it will be present in the child.
2667 void* ptr = mmap(nullptr, getpagesize(), 0, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2668 ASSERT_NE(MAP_FAILED, ptr);
2669
2670 StartProcess([ptr]() {
2671 ASSERT_EQ(0, crash_call(reinterpret_cast<uintptr_t>(ptr)));
2672 _exit(0);
2673 });
2674
2675 ASSERT_EQ(0, munmap(ptr, getpagesize()));
2676
2677 unique_fd output_fd;
2678 StartIntercept(&output_fd);
2679 FinishCrasher();
2680 AssertDeath(SIGSEGV);
2681
2682 int intercept_result;
2683 FinishIntercept(&intercept_result);
2684 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2685
2686 std::string result;
2687 ConsumeFd(std::move(output_fd), &result);
2688
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002689 std::string match_str = R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\), fault addr 0x)";
2690 match_str += format_full_pointer(reinterpret_cast<uintptr_t>(ptr));
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002691 ASSERT_MATCH(result, match_str);
2692
2693 ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
2694
2695 match_str = android::base::StringPrintf(R"(\n--->%s.*\n)", format_pointer(ptr).c_str());
2696 ASSERT_MATCH(result, match_str);
2697}
Christopher Ferris2038cc72021-09-15 03:57:10 +00002698
2699static constexpr uint32_t kDexData[] = {
2700 0x0a786564, 0x00383330, 0xc98b3ab8, 0xf3749d94, 0xaecca4d8, 0xffc7b09a, 0xdca9ca7f, 0x5be5deab,
2701 0x00000220, 0x00000070, 0x12345678, 0x00000000, 0x00000000, 0x0000018c, 0x00000008, 0x00000070,
2702 0x00000004, 0x00000090, 0x00000002, 0x000000a0, 0x00000000, 0x00000000, 0x00000003, 0x000000b8,
2703 0x00000001, 0x000000d0, 0x00000130, 0x000000f0, 0x00000122, 0x0000012a, 0x00000132, 0x00000146,
2704 0x00000151, 0x00000154, 0x00000158, 0x0000016d, 0x00000001, 0x00000002, 0x00000004, 0x00000006,
2705 0x00000004, 0x00000002, 0x00000000, 0x00000005, 0x00000002, 0x0000011c, 0x00000000, 0x00000000,
2706 0x00010000, 0x00000007, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000,
2707 0x00000003, 0x00000000, 0x0000017e, 0x00000000, 0x00010001, 0x00000001, 0x00000173, 0x00000004,
2708 0x00021070, 0x000e0000, 0x00010001, 0x00000000, 0x00000178, 0x00000001, 0x0000000e, 0x00000001,
2709 0x3c060003, 0x74696e69, 0x4c06003e, 0x6e69614d, 0x4c12003b, 0x6176616a, 0x6e616c2f, 0x624f2f67,
2710 0x7463656a, 0x4d09003b, 0x2e6e6961, 0x6176616a, 0x00560100, 0x004c5602, 0x6a4c5b13, 0x2f617661,
2711 0x676e616c, 0x7274532f, 0x3b676e69, 0x616d0400, 0x01006e69, 0x000e0700, 0x07000103, 0x0000000e,
2712 0x81000002, 0x01f00480, 0x02880901, 0x0000000c, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
2713 0x00000008, 0x00000070, 0x00000002, 0x00000004, 0x00000090, 0x00000003, 0x00000002, 0x000000a0,
2714 0x00000005, 0x00000003, 0x000000b8, 0x00000006, 0x00000001, 0x000000d0, 0x00002001, 0x00000002,
2715 0x000000f0, 0x00001001, 0x00000001, 0x0000011c, 0x00002002, 0x00000008, 0x00000122, 0x00002003,
2716 0x00000002, 0x00000173, 0x00002000, 0x00000001, 0x0000017e, 0x00001000, 0x00000001, 0x0000018c,
2717};
2718
2719TEST_F(CrasherTest, verify_dex_pc_with_function_name) {
2720 StartProcess([]() {
2721 TemporaryDir td;
2722 std::string tmp_so_name;
2723 if (!CopySharedLibrary(td.path, &tmp_so_name)) {
2724 _exit(1);
2725 }
2726
2727 // In order to cause libunwindstack to look for this __dex_debug_descriptor
2728 // move the library to which has a basename of libart.so.
2729 std::string art_so_name = android::base::Dirname(tmp_so_name) + "/libart.so";
2730 ASSERT_EQ(0, rename(tmp_so_name.c_str(), art_so_name.c_str()));
2731 void* handle = dlopen(art_so_name.c_str(), RTLD_NOW | RTLD_LOCAL);
2732 if (handle == nullptr) {
2733 _exit(1);
2734 }
2735
2736 void* ptr =
2737 mmap(nullptr, sizeof(kDexData), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2738 ASSERT_TRUE(ptr != MAP_FAILED);
2739 memcpy(ptr, kDexData, sizeof(kDexData));
2740 prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, sizeof(kDexData), "dex");
2741
2742 JITCodeEntry dex_entry = {.symfile_addr = reinterpret_cast<uintptr_t>(ptr),
2743 .symfile_size = sizeof(kDexData)};
2744
2745 JITDescriptor* dex_debug =
2746 reinterpret_cast<JITDescriptor*>(dlsym(handle, "__dex_debug_descriptor"));
2747 ASSERT_TRUE(dex_debug != nullptr);
2748 dex_debug->version = 1;
2749 dex_debug->action_flag = 0;
2750 dex_debug->relevant_entry = 0;
2751 dex_debug->first_entry = reinterpret_cast<uintptr_t>(&dex_entry);
2752
2753 // This sets the magic dex pc value for register 0, using the value
2754 // of register 1 + 0x102.
2755 asm(".cfi_escape "
2756 "0x16 /* DW_CFA_val_expression */, 0, 0x0a /* size */,"
2757 "0x0c /* DW_OP_const4u */, 0x44, 0x45, 0x58, 0x31, /* magic = 'DEX1' */"
2758 "0x13 /* DW_OP_drop */,"
2759 "0x92 /* DW_OP_bregx */, 1, 0x82, 0x02 /* 2-byte SLEB128 */");
2760
2761 // For each different architecture, set register one to the dex ptr mmap
2762 // created above. Then do a nullptr dereference to force a crash.
2763#if defined(__arm__)
2764 asm volatile(
2765 "mov r1, %[base]\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002766 "mov r2, #0\n"
2767 "str r2, [r2]\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002768 : [base] "+r"(ptr)
2769 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002770 : "r1", "r2", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002771#elif defined(__aarch64__)
2772 asm volatile(
2773 "mov x1, %[base]\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002774 "mov x2, #0\n"
2775 "str xzr, [x2]\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002776 : [base] "+r"(ptr)
2777 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002778 : "x1", "x2", "memory");
2779#elif defined(__riscv)
2780 // TODO: x1 is ra (the link register) on riscv64, so this might have
2781 // unintended consequences, but we'll need to change the .cfi_escape if so.
2782 asm volatile(
2783 "mv x1, %[base]\n"
2784 "sw zero, 0(zero)\n"
2785 : [base] "+r"(ptr)
2786 :
2787 : "x1", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002788#elif defined(__i386__)
2789 asm volatile(
2790 "mov %[base], %%ecx\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002791 "movl $0, 0\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002792 : [base] "+r"(ptr)
2793 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002794 : "ecx", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002795#elif defined(__x86_64__)
2796 asm volatile(
2797 "mov %[base], %%rdx\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002798 "movq $0, 0\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002799 : [base] "+r"(ptr)
2800 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002801 : "rdx", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002802#else
2803#error "Unsupported architecture"
2804#endif
2805 _exit(0);
2806 });
2807
2808 unique_fd output_fd;
2809 StartIntercept(&output_fd);
2810 FinishCrasher();
2811 AssertDeath(SIGSEGV);
2812
2813 int intercept_result;
2814 FinishIntercept(&intercept_result);
2815 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2816
2817 std::string result;
2818 ConsumeFd(std::move(output_fd), &result);
2819
2820 // Verify the process crashed properly.
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002821 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0*)");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002822
2823 // Now verify that the dex_pc frame includes a proper function name.
2824 ASSERT_MATCH(result, R"( \[anon:dex\] \(Main\.\<init\>\+2)");
2825}
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00002826
2827static std::string format_map_pointer(uintptr_t ptr) {
2828#if defined(__LP64__)
2829 return android::base::StringPrintf("%08x'%08x", static_cast<uint32_t>(ptr >> 32),
2830 static_cast<uint32_t>(ptr & 0xffffffff));
2831#else
2832 return android::base::StringPrintf("%08x", ptr);
2833#endif
2834}
2835
2836// Verify that map data is properly formatted.
2837TEST_F(CrasherTest, verify_map_format) {
2838 // Create multiple maps to make sure that the map data is formatted properly.
2839 void* none_map = mmap(nullptr, getpagesize(), 0, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2840 ASSERT_NE(MAP_FAILED, none_map);
2841 void* r_map = mmap(nullptr, getpagesize(), PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2842 ASSERT_NE(MAP_FAILED, r_map);
2843 void* w_map = mmap(nullptr, getpagesize(), PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2844 ASSERT_NE(MAP_FAILED, w_map);
2845 void* x_map = mmap(nullptr, getpagesize(), PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2846 ASSERT_NE(MAP_FAILED, x_map);
2847
2848 TemporaryFile tf;
2849 ASSERT_EQ(0x2000, lseek(tf.fd, 0x2000, SEEK_SET));
2850 char c = 'f';
2851 ASSERT_EQ(1, write(tf.fd, &c, 1));
2852 ASSERT_EQ(0x5000, lseek(tf.fd, 0x5000, SEEK_SET));
2853 ASSERT_EQ(1, write(tf.fd, &c, 1));
2854 ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
2855 void* file_map = mmap(nullptr, 0x3001, PROT_READ, MAP_PRIVATE, tf.fd, 0x2000);
2856 ASSERT_NE(MAP_FAILED, file_map);
2857
2858 StartProcess([]() { abort(); });
2859
2860 ASSERT_EQ(0, munmap(none_map, getpagesize()));
2861 ASSERT_EQ(0, munmap(r_map, getpagesize()));
2862 ASSERT_EQ(0, munmap(w_map, getpagesize()));
2863 ASSERT_EQ(0, munmap(x_map, getpagesize()));
2864 ASSERT_EQ(0, munmap(file_map, 0x3001));
2865
2866 unique_fd output_fd;
2867 StartIntercept(&output_fd);
2868 FinishCrasher();
2869 AssertDeath(SIGABRT);
2870 int intercept_result;
2871 FinishIntercept(&intercept_result);
2872
2873 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2874
2875 std::string result;
2876 ConsumeFd(std::move(output_fd), &result);
2877
2878 std::string match_str;
2879 // Verify none.
2880 match_str = android::base::StringPrintf(
2881 " %s-%s --- 0 1000\\n",
2882 format_map_pointer(reinterpret_cast<uintptr_t>(none_map)).c_str(),
2883 format_map_pointer(reinterpret_cast<uintptr_t>(none_map) + getpagesize() - 1).c_str());
2884 ASSERT_MATCH(result, match_str);
2885
2886 // Verify read-only.
2887 match_str = android::base::StringPrintf(
2888 " %s-%s r-- 0 1000\\n",
2889 format_map_pointer(reinterpret_cast<uintptr_t>(r_map)).c_str(),
2890 format_map_pointer(reinterpret_cast<uintptr_t>(r_map) + getpagesize() - 1).c_str());
2891 ASSERT_MATCH(result, match_str);
2892
2893 // Verify write-only.
2894 match_str = android::base::StringPrintf(
2895 " %s-%s -w- 0 1000\\n",
2896 format_map_pointer(reinterpret_cast<uintptr_t>(w_map)).c_str(),
2897 format_map_pointer(reinterpret_cast<uintptr_t>(w_map) + getpagesize() - 1).c_str());
2898 ASSERT_MATCH(result, match_str);
2899
2900 // Verify exec-only.
2901 match_str = android::base::StringPrintf(
2902 " %s-%s --x 0 1000\\n",
2903 format_map_pointer(reinterpret_cast<uintptr_t>(x_map)).c_str(),
2904 format_map_pointer(reinterpret_cast<uintptr_t>(x_map) + getpagesize() - 1).c_str());
2905 ASSERT_MATCH(result, match_str);
2906
2907 // Verify file map with non-zero offset and a name.
2908 match_str = android::base::StringPrintf(
2909 " %s-%s r-- 2000 4000 %s\\n",
2910 format_map_pointer(reinterpret_cast<uintptr_t>(file_map)).c_str(),
2911 format_map_pointer(reinterpret_cast<uintptr_t>(file_map) + 0x3fff).c_str(), tf.path);
2912 ASSERT_MATCH(result, match_str);
2913}
2914
2915// Verify that the tombstone map data is correct.
2916TEST_F(CrasherTest, verify_header) {
2917 StartProcess([]() { abort(); });
2918
2919 unique_fd output_fd;
2920 StartIntercept(&output_fd);
2921 FinishCrasher();
2922 AssertDeath(SIGABRT);
2923 int intercept_result;
2924 FinishIntercept(&intercept_result);
2925
2926 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2927
2928 std::string result;
2929 ConsumeFd(std::move(output_fd), &result);
2930
2931 std::string match_str = android::base::StringPrintf(
2932 "Build fingerprint: '%s'\\nRevision: '%s'\\n",
2933 android::base::GetProperty("ro.build.fingerprint", "unknown").c_str(),
2934 android::base::GetProperty("ro.revision", "unknown").c_str());
2935 match_str += android::base::StringPrintf("ABI: '%s'\n", ABI_STRING);
2936 ASSERT_MATCH(result, match_str);
2937}
2938
2939// Verify that the thread header is formatted properly.
2940TEST_F(CrasherTest, verify_thread_header) {
2941 void* shared_map =
2942 mmap(nullptr, sizeof(pid_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
2943 ASSERT_NE(MAP_FAILED, shared_map);
2944 memset(shared_map, 0, sizeof(pid_t));
2945
2946 StartProcess([&shared_map]() {
2947 std::atomic_bool tid_written;
2948 std::thread thread([&tid_written, &shared_map]() {
2949 pid_t tid = gettid();
2950 memcpy(shared_map, &tid, sizeof(pid_t));
2951 tid_written = true;
2952 volatile bool done = false;
2953 while (!done)
2954 ;
2955 });
2956 thread.detach();
2957 while (!tid_written.load(std::memory_order_acquire))
2958 ;
2959 abort();
2960 });
2961
2962 pid_t primary_pid = crasher_pid;
2963
2964 unique_fd output_fd;
2965 StartIntercept(&output_fd);
2966 FinishCrasher();
2967 AssertDeath(SIGABRT);
2968 int intercept_result;
2969 FinishIntercept(&intercept_result);
2970 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2971
2972 // Read the tid data out.
2973 pid_t tid;
2974 memcpy(&tid, shared_map, sizeof(pid_t));
2975 ASSERT_NE(0, tid);
2976
2977 ASSERT_EQ(0, munmap(shared_map, sizeof(pid_t)));
2978
2979 std::string result;
2980 ConsumeFd(std::move(output_fd), &result);
2981
2982 // Verify that there are two headers, one where the tid is "primary_pid"
2983 // and the other where the tid is "tid".
2984 std::string match_str = android::base::StringPrintf("pid: %d, tid: %d, name: .* >>> .* <<<\\n",
2985 primary_pid, primary_pid);
2986 ASSERT_MATCH(result, match_str);
2987
2988 match_str =
2989 android::base::StringPrintf("pid: %d, tid: %d, name: .* >>> .* <<<\\n", primary_pid, tid);
2990 ASSERT_MATCH(result, match_str);
2991}
2992
2993// Verify that there is a BuildID present in the map section and set properly.
2994TEST_F(CrasherTest, verify_build_id) {
2995 StartProcess([]() { abort(); });
2996
2997 unique_fd output_fd;
2998 StartIntercept(&output_fd);
2999 FinishCrasher();
3000 AssertDeath(SIGABRT);
3001 int intercept_result;
3002 FinishIntercept(&intercept_result);
3003 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3004
3005 std::string result;
3006 ConsumeFd(std::move(output_fd), &result);
3007
3008 // Find every /system or /apex lib and verify the BuildID is displayed
3009 // properly.
3010 bool found_valid_elf = false;
3011 std::smatch match;
3012 std::regex build_id_regex(R"( ((/system/|/apex/)\S+) \(BuildId: ([^\)]+)\))");
3013 for (std::string prev_file; std::regex_search(result, match, build_id_regex);
3014 result = match.suffix()) {
3015 if (prev_file == match[1]) {
3016 // Already checked this file.
3017 continue;
3018 }
3019
3020 prev_file = match[1];
Christopher Ferris15038902023-11-10 00:05:49 -08003021 auto elf_memory = unwindstack::Memory::CreateFileMemory(prev_file, 0);
3022 unwindstack::Elf elf(elf_memory);
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00003023 if (!elf.Init() || !elf.valid()) {
3024 // Skipping invalid elf files.
3025 continue;
3026 }
3027 ASSERT_EQ(match[3], elf.GetPrintableBuildID());
3028
3029 found_valid_elf = true;
3030 }
3031 ASSERT_TRUE(found_valid_elf) << "Did not find any elf files with valid BuildIDs to check.";
3032}
Christopher Ferrisbda10642023-04-24 18:14:53 -07003033
3034const char kLogMessage[] = "Should not see this log message.";
3035
3036// Verify that the logd process does not read the log.
3037TEST_F(CrasherTest, logd_skips_reading_logs) {
3038 StartProcess([]() {
3039 pthread_setname_np(pthread_self(), "logd");
3040 LOG(INFO) << kLogMessage;
3041 abort();
3042 });
3043
3044 unique_fd output_fd;
3045 StartIntercept(&output_fd);
3046 FinishCrasher();
3047 AssertDeath(SIGABRT);
3048 int intercept_result;
3049 FinishIntercept(&intercept_result);
3050 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3051
3052 std::string result;
3053 ConsumeFd(std::move(output_fd), &result);
3054 // logd should not contain our log message.
3055 ASSERT_NOT_MATCH(result, kLogMessage);
3056}
3057
3058// Verify that the logd process does not read the log when the non-main
3059// thread crashes.
3060TEST_F(CrasherTest, logd_skips_reading_logs_not_main_thread) {
3061 StartProcess([]() {
3062 pthread_setname_np(pthread_self(), "logd");
3063 LOG(INFO) << kLogMessage;
3064
3065 std::thread thread([]() {
3066 pthread_setname_np(pthread_self(), "not_logd_thread");
3067 // Raise the signal on the side thread.
3068 raise_debugger_signal(kDebuggerdTombstone);
3069 });
3070 thread.join();
3071 _exit(0);
3072 });
3073
3074 unique_fd output_fd;
3075 StartIntercept(&output_fd, kDebuggerdTombstone);
3076 FinishCrasher();
3077 AssertDeath(0);
3078
3079 int intercept_result;
3080 FinishIntercept(&intercept_result);
3081 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3082
3083 std::string result;
3084 ConsumeFd(std::move(output_fd), &result);
3085 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
3086 ASSERT_NOT_MATCH(result, kLogMessage);
3087}
Christopher Ferris98d62422023-05-24 20:01:10 +00003088
3089// Disable this test since there is a high liklihood that this would
3090// be flaky since it requires 500 messages being in the log.
3091TEST_F(CrasherTest, DISABLED_max_log_messages) {
3092 StartProcess([]() {
3093 for (size_t i = 0; i < 600; i++) {
3094 LOG(INFO) << "Message number " << i;
3095 }
3096 abort();
3097 });
3098
3099 unique_fd output_fd;
3100 StartIntercept(&output_fd);
3101 FinishCrasher();
3102 AssertDeath(SIGABRT);
3103 int intercept_result;
3104 FinishIntercept(&intercept_result);
3105 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3106
3107 std::string result;
3108 ConsumeFd(std::move(output_fd), &result);
3109 ASSERT_NOT_MATCH(result, "Message number 99");
3110 ASSERT_MATCH(result, "Message number 100");
3111 ASSERT_MATCH(result, "Message number 599");
3112}
3113
3114TEST_F(CrasherTest, log_with_newline) {
3115 StartProcess([]() {
3116 LOG(INFO) << "This line has a newline.\nThis is on the next line.";
3117 abort();
3118 });
3119
3120 unique_fd output_fd;
3121 StartIntercept(&output_fd);
3122 FinishCrasher();
3123 AssertDeath(SIGABRT);
3124 int intercept_result;
3125 FinishIntercept(&intercept_result);
3126 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3127
3128 std::string result;
3129 ConsumeFd(std::move(output_fd), &result);
3130 ASSERT_MATCH(result, ":\\s*This line has a newline.");
3131 ASSERT_MATCH(result, ":\\s*This is on the next line.");
3132}