blob: 7c52e6e50de9caec0c18bd7734c98049c1bbdad4 [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>
Florian Mayere6462f92024-02-28 11:12:11 -080024#include <setjmp.h>
Josh Gaocdea7502017-11-01 15:00:40 -070025#include <stdlib.h>
Josh Gao502cfd22017-02-17 01:39:15 -080026#include <sys/capability.h>
Peter Collingbournefe8997a2020-07-20 15:08:52 -070027#include <sys/mman.h>
Josh Gaofca7ca32017-01-23 12:05:35 -080028#include <sys/prctl.h>
Josh Gaofd13bf02017-08-18 15:37:26 -070029#include <sys/ptrace.h>
Josh Gao70adac62018-02-22 11:38:33 -080030#include <sys/resource.h>
Dan Albertc38057a2017-10-11 11:35:40 -070031#include <sys/syscall.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070032#include <sys/types.h>
Josh Gaofd13bf02017-08-18 15:37:26 -070033#include <unistd.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070034
35#include <chrono>
36#include <regex>
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +000037#include <set>
Christopher Ferrisfe751c52021-04-16 09:40:40 -070038#include <string>
Josh Gaocbe70cb2016-10-18 18:17:52 -070039#include <thread>
40
Florian Mayer920d95b2024-02-14 12:57:09 -080041#include <android/crash_detail.h>
Christopher Ferris22035cc2023-01-31 17:50:22 -080042#include <android/dlext.h>
Josh Gaobf06a402018-08-27 16:34:01 -070043#include <android/fdsan.h>
Josh Gao502cfd22017-02-17 01:39:15 -080044#include <android/set_abort_message.h>
Mitch Phillips7168a212021-03-09 16:53:23 -080045#include <bionic/malloc.h>
Peter Collingbournef8622522020-04-07 14:07:32 -070046#include <bionic/mte.h>
Josh Gaoa48b41b2019-12-13 14:11:04 -080047#include <bionic/reserved_signals.h>
Josh Gao502cfd22017-02-17 01:39:15 -080048
Josh Gao5f87bbd2019-01-09 17:01:49 -080049#include <android-base/cmsg.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070050#include <android-base/file.h>
51#include <android-base/logging.h>
Josh Gao2e7b8e22017-05-04 17:12:57 -070052#include <android-base/macros.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070053#include <android-base/parseint.h>
54#include <android-base/properties.h>
Josh Gao2b22ae12018-09-12 14:51:03 -070055#include <android-base/stringprintf.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070056#include <android-base/strings.h>
Josh Gao30171a82017-04-27 19:48:44 -070057#include <android-base/test_utils.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070058#include <android-base/unique_fd.h>
59#include <cutils/sockets.h>
Mitch Phillips78f06702021-06-01 14:35:43 -070060#include <gmock/gmock.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070061#include <gtest/gtest.h>
62
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +000063#include <unwindstack/Elf.h>
64#include <unwindstack/Memory.h>
65
Josh Gaoe04ca272018-01-16 15:38:17 -080066#include <libminijail.h>
67#include <scoped_minijail.h>
68
Christopher Ferris2038cc72021-09-15 03:57:10 +000069#include "crash_test.h"
Narayan Kamath2d377cd2017-05-10 10:58:59 +010070#include "debuggerd/handler.h"
Mitch Phillips18ce5422023-01-19 14:23:49 -080071#include "gtest/gtest.h"
Mitch Phillips5ddcea22021-04-19 09:59:17 -070072#include "libdebuggerd/utility.h"
Narayan Kamath2d377cd2017-05-10 10:58:59 +010073#include "protocol.h"
74#include "tombstoned/tombstoned.h"
75#include "util.h"
76
Josh Gaocbe70cb2016-10-18 18:17:52 -070077using namespace std::chrono_literals;
Josh Gao5f87bbd2019-01-09 17:01:49 -080078
79using android::base::SendFileDescriptors;
Josh Gaocbe70cb2016-10-18 18:17:52 -070080using android::base::unique_fd;
Mitch Phillips78f06702021-06-01 14:35:43 -070081using ::testing::HasSubstr;
Josh Gaocbe70cb2016-10-18 18:17:52 -070082
83#if defined(__LP64__)
Josh Gaocbe70cb2016-10-18 18:17:52 -070084#define ARCH_SUFFIX "64"
85#else
Josh Gaocbe70cb2016-10-18 18:17:52 -070086#define ARCH_SUFFIX ""
87#endif
88
Elliott Hughese4781d52021-03-17 09:15:15 -070089constexpr char kWaitForDebuggerKey[] = "debug.debuggerd.wait_for_debugger";
Josh Gaocbe70cb2016-10-18 18:17:52 -070090
91#define TIMEOUT(seconds, expr) \
92 [&]() { \
93 struct sigaction old_sigaction; \
94 struct sigaction new_sigaction = {}; \
95 new_sigaction.sa_handler = [](int) {}; \
Christopher Ferris16a7bc22022-01-31 13:08:54 -080096 if (sigaction(SIGALRM, &new_sigaction, &old_sigaction) != 0) { \
Josh Gaocbe70cb2016-10-18 18:17:52 -070097 err(1, "sigaction failed"); \
98 } \
Mattias Simonsson38ab0452023-11-08 12:02:46 +000099 alarm(seconds * android::base::HwTimeoutMultiplier()); \
Josh Gaocbe70cb2016-10-18 18:17:52 -0700100 auto value = expr; \
101 int saved_errno = errno; \
102 if (sigaction(SIGALRM, &old_sigaction, nullptr) != 0) { \
103 err(1, "sigaction failed"); \
104 } \
105 alarm(0); \
106 errno = saved_errno; \
107 return value; \
108 }()
109
Chih-Hung Hsieh3249b3a2018-05-11 16:01:21 -0700110// Backtrace frame dump could contain:
111// #01 pc 0001cded /data/tmp/debuggerd_test32 (raise_debugger_signal+80)
112// or
113// #01 pc 00022a09 /data/tmp/debuggerd_test32 (offset 0x12000) (raise_debugger_signal+80)
Josh Gaoe04ca272018-01-16 15:38:17 -0800114#define ASSERT_BACKTRACE_FRAME(result, frame_name) \
Chih-Hung Hsieh3249b3a2018-05-11 16:01:21 -0700115 ASSERT_MATCH(result, \
116 R"(#\d\d pc [0-9a-f]+\s+ \S+ (\(offset 0x[0-9a-f]+\) )?\()" frame_name R"(\+)");
Jaesung Chung58778e12017-06-15 18:20:34 +0900117
Narayan Kamatha73df602017-05-24 15:07:25 +0100118static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, unique_fd* output_fd,
Christopher Ferrisb92b52c2023-10-16 19:14:28 -0700119 InterceptResponse* response, DebuggerdDumpType intercept_type) {
Josh Gao460b3362017-03-30 16:40:47 -0700120 intercept_fd->reset(socket_local_client(kTombstonedInterceptSocketName,
121 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
122 if (intercept_fd->get() == -1) {
123 FAIL() << "failed to contact tombstoned: " << strerror(errno);
124 }
125
Nick Desaulniers67d52aa2019-10-07 23:28:15 -0700126 InterceptRequest req = {
127 .dump_type = intercept_type,
128 .pid = target_pid,
129 };
Josh Gao460b3362017-03-30 16:40:47 -0700130
131 unique_fd output_pipe_write;
132 if (!Pipe(output_fd, &output_pipe_write)) {
133 FAIL() << "failed to create output pipe: " << strerror(errno);
134 }
135
136 std::string pipe_size_str;
137 int pipe_buffer_size;
138 if (!android::base::ReadFileToString("/proc/sys/fs/pipe-max-size", &pipe_size_str)) {
139 FAIL() << "failed to read /proc/sys/fs/pipe-max-size: " << strerror(errno);
140 }
141
142 pipe_size_str = android::base::Trim(pipe_size_str);
143
144 if (!android::base::ParseInt(pipe_size_str.c_str(), &pipe_buffer_size, 0)) {
145 FAIL() << "failed to parse pipe max size";
146 }
147
148 if (fcntl(output_fd->get(), F_SETPIPE_SZ, pipe_buffer_size) != pipe_buffer_size) {
149 FAIL() << "failed to set pipe size: " << strerror(errno);
150 }
151
Josh Gao5675f3c2017-06-01 12:19:53 -0700152 ASSERT_GE(pipe_buffer_size, 1024 * 1024);
153
Josh Gao5f87bbd2019-01-09 17:01:49 -0800154 ssize_t rc = SendFileDescriptors(intercept_fd->get(), &req, sizeof(req), output_pipe_write.get());
155 output_pipe_write.reset();
156 if (rc != sizeof(req)) {
Josh Gao460b3362017-03-30 16:40:47 -0700157 FAIL() << "failed to send output fd to tombstoned: " << strerror(errno);
158 }
159
Christopher Ferrisb92b52c2023-10-16 19:14:28 -0700160 rc = TEMP_FAILURE_RETRY(read(intercept_fd->get(), response, sizeof(*response)));
Josh Gao460b3362017-03-30 16:40:47 -0700161 if (rc == -1) {
162 FAIL() << "failed to read response from tombstoned: " << strerror(errno);
163 } else if (rc == 0) {
164 FAIL() << "failed to read response from tombstoned (EOF)";
Christopher Ferrisb92b52c2023-10-16 19:14:28 -0700165 } else if (rc != sizeof(*response)) {
166 FAIL() << "received packet of unexpected length from tombstoned: expected " << sizeof(*response)
Josh Gao460b3362017-03-30 16:40:47 -0700167 << ", received " << rc;
168 }
Josh Gao460b3362017-03-30 16:40:47 -0700169}
170
Elliott Hughesd13ea522022-01-13 09:20:26 -0800171static bool pac_supported() {
172#if defined(__aarch64__)
173 return getauxval(AT_HWCAP) & HWCAP_PACA;
174#else
175 return false;
176#endif
177}
178
Josh Gaocbe70cb2016-10-18 18:17:52 -0700179class CrasherTest : public ::testing::Test {
180 public:
181 pid_t crasher_pid = -1;
Elliott Hughese4781d52021-03-17 09:15:15 -0700182 bool previous_wait_for_debugger;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700183 unique_fd crasher_pipe;
184 unique_fd intercept_fd;
185
186 CrasherTest();
187 ~CrasherTest();
188
Narayan Kamatha73df602017-05-24 15:07:25 +0100189 void StartIntercept(unique_fd* output_fd, DebuggerdDumpType intercept_type = kDebuggerdTombstone);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700190
191 // Returns -1 if we fail to read a response from tombstoned, otherwise the received return code.
192 void FinishIntercept(int* result);
193
Josh Gao2e7b8e22017-05-04 17:12:57 -0700194 void StartProcess(std::function<void()> function, std::function<pid_t()> forker = fork);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700195 void StartCrasher(const std::string& crash_type);
196 void FinishCrasher();
197 void AssertDeath(int signo);
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700198
199 static void Trap(void* ptr);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700200};
201
202CrasherTest::CrasherTest() {
Elliott Hughese4781d52021-03-17 09:15:15 -0700203 previous_wait_for_debugger = android::base::GetBoolProperty(kWaitForDebuggerKey, false);
204 android::base::SetProperty(kWaitForDebuggerKey, "0");
205
206 // Clear the old property too, just in case someone's been using it
207 // on this device. (We only document the new name, but we still support
208 // the old name so we don't break anyone's existing setups.)
209 android::base::SetProperty("debug.debuggerd.wait_for_gdb", "0");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700210}
211
212CrasherTest::~CrasherTest() {
213 if (crasher_pid != -1) {
214 kill(crasher_pid, SIGKILL);
215 int status;
Christopher Ferris172b0a02019-09-18 17:48:30 -0700216 TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, WUNTRACED));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700217 }
218
Elliott Hughese4781d52021-03-17 09:15:15 -0700219 android::base::SetProperty(kWaitForDebuggerKey, previous_wait_for_debugger ? "1" : "0");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700220}
221
Narayan Kamatha73df602017-05-24 15:07:25 +0100222void CrasherTest::StartIntercept(unique_fd* output_fd, DebuggerdDumpType intercept_type) {
Josh Gaocbe70cb2016-10-18 18:17:52 -0700223 if (crasher_pid == -1) {
224 FAIL() << "crasher hasn't been started";
225 }
226
Christopher Ferrisb92b52c2023-10-16 19:14:28 -0700227 InterceptResponse response = {};
228 tombstoned_intercept(crasher_pid, &this->intercept_fd, output_fd, &response, intercept_type);
229 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
230 << "Error message: " << response.error_message;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700231}
232
233void CrasherTest::FinishIntercept(int* result) {
234 InterceptResponse response;
235
Christopher Ferris11555f02019-09-20 14:18:55 -0700236 ssize_t rc = TIMEOUT(30, read(intercept_fd.get(), &response, sizeof(response)));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700237 if (rc == -1) {
238 FAIL() << "failed to read response from tombstoned: " << strerror(errno);
239 } else if (rc == 0) {
240 *result = -1;
241 } else if (rc != sizeof(response)) {
242 FAIL() << "received packet of unexpected length from tombstoned: expected " << sizeof(response)
243 << ", received " << rc;
244 } else {
Josh Gao460b3362017-03-30 16:40:47 -0700245 *result = response.status == InterceptStatus::kStarted ? 1 : 0;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700246 }
247}
248
Josh Gao2e7b8e22017-05-04 17:12:57 -0700249void CrasherTest::StartProcess(std::function<void()> function, std::function<pid_t()> forker) {
Josh Gaofca7ca32017-01-23 12:05:35 -0800250 unique_fd read_pipe;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700251 unique_fd crasher_read_pipe;
252 if (!Pipe(&crasher_read_pipe, &crasher_pipe)) {
253 FAIL() << "failed to create pipe: " << strerror(errno);
254 }
255
Josh Gao2e7b8e22017-05-04 17:12:57 -0700256 crasher_pid = forker();
Josh Gaocbe70cb2016-10-18 18:17:52 -0700257 if (crasher_pid == -1) {
258 FAIL() << "fork failed: " << strerror(errno);
259 } else if (crasher_pid == 0) {
Josh Gao502cfd22017-02-17 01:39:15 -0800260 char dummy;
261 crasher_pipe.reset();
262 TEMP_FAILURE_RETRY(read(crasher_read_pipe.get(), &dummy, 1));
Josh Gaofca7ca32017-01-23 12:05:35 -0800263 function();
264 _exit(0);
265 }
266}
267
Josh Gaocbe70cb2016-10-18 18:17:52 -0700268void CrasherTest::FinishCrasher() {
269 if (crasher_pipe == -1) {
270 FAIL() << "crasher pipe uninitialized";
271 }
272
Christopher Ferris172b0a02019-09-18 17:48:30 -0700273 ssize_t rc = TEMP_FAILURE_RETRY(write(crasher_pipe.get(), "\n", 1));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700274 if (rc == -1) {
275 FAIL() << "failed to write to crasher pipe: " << strerror(errno);
276 } else if (rc == 0) {
277 FAIL() << "crasher pipe was closed";
278 }
279}
280
281void CrasherTest::AssertDeath(int signo) {
282 int status;
Christopher Ferris11555f02019-09-20 14:18:55 -0700283 pid_t pid = TIMEOUT(30, waitpid(crasher_pid, &status, 0));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700284 if (pid != crasher_pid) {
Christopher Ferrisafc0ff72019-06-26 15:08:51 -0700285 printf("failed to wait for crasher (expected pid %d, return value %d): %s\n", crasher_pid, pid,
286 strerror(errno));
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700287 sleep(100);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700288 FAIL() << "failed to wait for crasher: " << strerror(errno);
289 }
290
Josh Gaoe06f2a42017-04-27 16:50:38 -0700291 if (signo == 0) {
Christopher Ferris67022562021-04-16 13:30:32 -0700292 ASSERT_TRUE(WIFEXITED(status)) << "Terminated due to unexpected signal " << WTERMSIG(status);
Josh Gaoe06f2a42017-04-27 16:50:38 -0700293 ASSERT_EQ(0, WEXITSTATUS(signo));
294 } else {
295 ASSERT_FALSE(WIFEXITED(status));
296 ASSERT_TRUE(WIFSIGNALED(status)) << "crasher didn't terminate via a signal";
297 ASSERT_EQ(signo, WTERMSIG(status));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700298 }
Josh Gaocbe70cb2016-10-18 18:17:52 -0700299 crasher_pid = -1;
300}
301
302static void ConsumeFd(unique_fd fd, std::string* output) {
Kelvin Zhang786dac32023-06-15 16:23:56 -0700303 ASSERT_TRUE(android::base::ReadFdToString(fd, output));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700304}
305
Mitch Phillips78f06702021-06-01 14:35:43 -0700306class LogcatCollector {
307 public:
308 LogcatCollector() { system("logcat -c"); }
309
310 void Collect(std::string* output) {
311 FILE* cmd_stdout = popen("logcat -d '*:S DEBUG'", "r");
312 ASSERT_NE(cmd_stdout, nullptr);
313 unique_fd tmp_fd(TEMP_FAILURE_RETRY(dup(fileno(cmd_stdout))));
314 ConsumeFd(std::move(tmp_fd), output);
315 pclose(cmd_stdout);
316 }
317};
318
Josh Gaocbe70cb2016-10-18 18:17:52 -0700319TEST_F(CrasherTest, smoke) {
320 int intercept_result;
321 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -0800322 StartProcess([]() {
323 *reinterpret_cast<volatile char*>(0xdead) = '1';
324 });
325
Josh Gaocbe70cb2016-10-18 18:17:52 -0700326 StartIntercept(&output_fd);
327 FinishCrasher();
328 AssertDeath(SIGSEGV);
329 FinishIntercept(&intercept_result);
330
331 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
332
333 std::string result;
334 ConsumeFd(std::move(output_fd), &result);
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800335#ifdef __LP64__
336 ASSERT_MATCH(result,
337 R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x000000000000dead)");
338#else
339 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0000dead)");
340#endif
Peter Collingbourne864f15d2020-09-14 20:27:36 -0700341
342 if (mte_supported()) {
343 // Test that the default TAGGED_ADDR_CTRL value is set.
Peter Collingbourne47d784e2021-11-05 18:40:52 -0700344 ASSERT_MATCH(result, R"(tagged_addr_ctrl: 000000000007fff3)"
345 R"( \(PR_TAGGED_ADDR_ENABLE, PR_MTE_TCF_SYNC, mask 0xfffe\))");
Peter Collingbourne864f15d2020-09-14 20:27:36 -0700346 }
Elliott Hughesd13ea522022-01-13 09:20:26 -0800347
348 if (pac_supported()) {
349 // Test that the default PAC_ENABLED_KEYS value is set.
350 ASSERT_MATCH(result, R"(pac_enabled_keys: 000000000000000f)"
351 R"( \(PR_PAC_APIAKEY, PR_PAC_APIBKEY, PR_PAC_APDAKEY, PR_PAC_APDBKEY\))");
352 }
Josh Gaocbe70cb2016-10-18 18:17:52 -0700353}
354
Peter Collingbournef03af882020-03-20 18:09:00 -0700355TEST_F(CrasherTest, tagged_fault_addr) {
356#if !defined(__aarch64__)
357 GTEST_SKIP() << "Requires aarch64";
358#endif
Florian Mayerb4979292022-04-15 14:35:17 -0700359 // HWASan crashes with SIGABRT on tag mismatch.
360 SKIP_WITH_HWASAN;
Peter Collingbournef03af882020-03-20 18:09:00 -0700361 int intercept_result;
362 unique_fd output_fd;
363 StartProcess([]() {
364 *reinterpret_cast<volatile char*>(0x100000000000dead) = '1';
365 });
366
367 StartIntercept(&output_fd);
368 FinishCrasher();
369 AssertDeath(SIGSEGV);
370 FinishIntercept(&intercept_result);
371
372 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
373
374 std::string result;
375 ConsumeFd(std::move(output_fd), &result);
376
377 // The address can either be tagged (new kernels) or untagged (old kernels).
378 ASSERT_MATCH(
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800379 result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x[01]00000000000dead)");
Peter Collingbournef03af882020-03-20 18:09:00 -0700380}
381
Evgenii Stepanov361455e2022-10-13 16:23:08 -0700382void CrasherTest::Trap(void* ptr) {
383 void (*volatile f)(void*) = nullptr;
384 __asm__ __volatile__("" : : "r"(f) : "memory");
385 f(ptr);
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700386}
387
388TEST_F(CrasherTest, heap_addr_in_register) {
389#if defined(__i386__)
390 GTEST_SKIP() << "architecture does not pass arguments in registers";
391#endif
Florian Mayerb4979292022-04-15 14:35:17 -0700392 // The memory dump in HWASan crashes sadly shows the memory near the registers
393 // in the HWASan dump function, rather the faulting context. This is a known
394 // issue.
395 SKIP_WITH_HWASAN;
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700396 int intercept_result;
397 unique_fd output_fd;
398 StartProcess([]() {
399 // Crash with a heap pointer in the first argument register.
400 Trap(malloc(1));
401 });
402
403 StartIntercept(&output_fd);
404 FinishCrasher();
405 int status;
406 ASSERT_EQ(crasher_pid, TIMEOUT(30, waitpid(crasher_pid, &status, 0)));
407 ASSERT_TRUE(WIFSIGNALED(status)) << "crasher didn't terminate via a signal";
408 // Don't test the signal number because different architectures use different signals for
409 // __builtin_trap().
410 FinishIntercept(&intercept_result);
411
412 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
413
414 std::string result;
415 ConsumeFd(std::move(output_fd), &result);
416
417#if defined(__aarch64__)
Peter Collingbourne0ea08c22021-02-05 14:59:08 -0800418 ASSERT_MATCH(result, "memory near x0 \\(\\[anon:");
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700419#elif defined(__arm__)
Peter Collingbourne0ea08c22021-02-05 14:59:08 -0800420 ASSERT_MATCH(result, "memory near r0 \\(\\[anon:");
haocheng.zy@linux.alibaba.com3f4d0362022-09-10 11:38:19 +0800421#elif defined(__riscv)
422 ASSERT_MATCH(result, "memory near a0 \\(\\[anon:");
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700423#elif defined(__x86_64__)
Peter Collingbourne0ea08c22021-02-05 14:59:08 -0800424 ASSERT_MATCH(result, "memory near rdi \\(\\[anon:");
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700425#else
426 ASSERT_TRUE(false) << "unsupported architecture";
427#endif
428}
429
Peter Collingbournecd278072020-12-21 14:08:38 -0800430#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700431static void SetTagCheckingLevelSync() {
Elliott Hughes03b283a2021-01-15 11:34:26 -0800432 if (mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_SYNC) == 0) {
Peter Collingbournef8622522020-04-07 14:07:32 -0700433 abort();
434 }
435}
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800436
437static void SetTagCheckingLevelAsync() {
438 if (mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_ASYNC) == 0) {
439 abort();
440 }
441}
Peter Collingbournef8622522020-04-07 14:07:32 -0700442#endif
443
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800444struct SizeParamCrasherTest : CrasherTest, testing::WithParamInterface<size_t> {};
445
Peter Collingbourneaa544792021-05-13 13:53:37 -0700446INSTANTIATE_TEST_SUITE_P(Sizes, SizeParamCrasherTest, testing::Values(0, 16, 131072));
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800447
448TEST_P(SizeParamCrasherTest, mte_uaf) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800449#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700450 if (!mte_supported()) {
451 GTEST_SKIP() << "Requires MTE";
452 }
453
Peter Collingbourneaa544792021-05-13 13:53:37 -0700454 // Any UAF on a zero-sized allocation will be out-of-bounds so it won't be reported.
455 if (GetParam() == 0) {
456 return;
457 }
458
Mitch Phillips78f06702021-06-01 14:35:43 -0700459 LogcatCollector logcat_collector;
460
Peter Collingbournef8622522020-04-07 14:07:32 -0700461 int intercept_result;
462 unique_fd output_fd;
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800463 StartProcess([&]() {
Peter Collingbournef8622522020-04-07 14:07:32 -0700464 SetTagCheckingLevelSync();
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800465 volatile int* p = (volatile int*)malloc(GetParam());
Peter Collingbournef8622522020-04-07 14:07:32 -0700466 free((void *)p);
467 p[0] = 42;
468 });
469
470 StartIntercept(&output_fd);
471 FinishCrasher();
472 AssertDeath(SIGSEGV);
473 FinishIntercept(&intercept_result);
474
475 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
476
Mitch Phillips78f06702021-06-01 14:35:43 -0700477 std::vector<std::string> log_sources(2);
478 ConsumeFd(std::move(output_fd), &log_sources[0]);
479 logcat_collector.Collect(&log_sources[1]);
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700480 // Tag dump only available in the tombstone, not logcat.
481 ASSERT_MATCH(log_sources[0], "Memory tags around the fault address");
Peter Collingbournef8622522020-04-07 14:07:32 -0700482
Mitch Phillips78f06702021-06-01 14:35:43 -0700483 for (const auto& result : log_sources) {
484 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
485 ASSERT_MATCH(result, R"(Cause: \[MTE\]: Use After Free, 0 bytes into a )" +
486 std::to_string(GetParam()) + R"(-byte allocation)");
487 ASSERT_MATCH(result, R"(deallocated by thread .*?\n.*#00 pc)");
488 ASSERT_MATCH(result, R"((^|\s)allocated by thread .*?\n.*#00 pc)");
489 }
Peter Collingbournef8622522020-04-07 14:07:32 -0700490#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800491 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournef8622522020-04-07 14:07:32 -0700492#endif
493}
494
Peter Collingbournedc476342021-05-12 15:56:43 -0700495TEST_P(SizeParamCrasherTest, mte_oob_uaf) {
496#if defined(__aarch64__)
497 if (!mte_supported()) {
498 GTEST_SKIP() << "Requires MTE";
499 }
500
501 int intercept_result;
502 unique_fd output_fd;
503 StartProcess([&]() {
504 SetTagCheckingLevelSync();
505 volatile int* p = (volatile int*)malloc(GetParam());
506 free((void *)p);
507 p[-1] = 42;
508 });
509
510 StartIntercept(&output_fd);
511 FinishCrasher();
512 AssertDeath(SIGSEGV);
513 FinishIntercept(&intercept_result);
514
515 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
516
517 std::string result;
518 ConsumeFd(std::move(output_fd), &result);
519
520 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
521 ASSERT_NOT_MATCH(result, R"(Cause: \[MTE\]: Use After Free, 4 bytes left)");
522#else
523 GTEST_SKIP() << "Requires aarch64";
524#endif
525}
526
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800527TEST_P(SizeParamCrasherTest, mte_overflow) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800528#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700529 if (!mte_supported()) {
530 GTEST_SKIP() << "Requires MTE";
531 }
532
Mitch Phillips78f06702021-06-01 14:35:43 -0700533 LogcatCollector logcat_collector;
Peter Collingbournef8622522020-04-07 14:07:32 -0700534 int intercept_result;
535 unique_fd output_fd;
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800536 StartProcess([&]() {
Peter Collingbournef8622522020-04-07 14:07:32 -0700537 SetTagCheckingLevelSync();
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800538 volatile char* p = (volatile char*)malloc(GetParam());
539 p[GetParam()] = 42;
Peter Collingbournef8622522020-04-07 14:07:32 -0700540 });
541
542 StartIntercept(&output_fd);
543 FinishCrasher();
544 AssertDeath(SIGSEGV);
545 FinishIntercept(&intercept_result);
546
547 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
548
Mitch Phillips78f06702021-06-01 14:35:43 -0700549 std::vector<std::string> log_sources(2);
550 ConsumeFd(std::move(output_fd), &log_sources[0]);
551 logcat_collector.Collect(&log_sources[1]);
Peter Collingbournef8622522020-04-07 14:07:32 -0700552
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700553 // Tag dump only in tombstone, not logcat, and tagging is not used for
554 // overflow protection in the scudo secondary (guard pages are used instead).
555 if (GetParam() < 0x10000) {
556 ASSERT_MATCH(log_sources[0], "Memory tags around the fault address");
557 }
558
Mitch Phillips78f06702021-06-01 14:35:43 -0700559 for (const auto& result : log_sources) {
560 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
561 ASSERT_MATCH(result, R"(Cause: \[MTE\]: Buffer Overflow, 0 bytes right of a )" +
562 std::to_string(GetParam()) + R"(-byte allocation)");
563 ASSERT_MATCH(result, R"((^|\s)allocated by thread .*?\n.*#00 pc)");
564 }
Peter Collingbournef8622522020-04-07 14:07:32 -0700565#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800566 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournef8622522020-04-07 14:07:32 -0700567#endif
568}
569
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800570TEST_P(SizeParamCrasherTest, mte_underflow) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800571#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700572 if (!mte_supported()) {
573 GTEST_SKIP() << "Requires MTE";
574 }
575
576 int intercept_result;
577 unique_fd output_fd;
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800578 StartProcess([&]() {
Peter Collingbournef8622522020-04-07 14:07:32 -0700579 SetTagCheckingLevelSync();
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800580 volatile int* p = (volatile int*)malloc(GetParam());
Peter Collingbournef8622522020-04-07 14:07:32 -0700581 p[-1] = 42;
582 });
583
584 StartIntercept(&output_fd);
585 FinishCrasher();
586 AssertDeath(SIGSEGV);
587 FinishIntercept(&intercept_result);
588
589 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
590
591 std::string result;
592 ConsumeFd(std::move(output_fd), &result);
593
594 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 9 \(SEGV_MTESERR\))");
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800595 ASSERT_MATCH(result, R"(Cause: \[MTE\]: Buffer Underflow, 4 bytes left of a )" +
Peter Collingbourne1a1f7d72021-03-08 16:53:54 -0800596 std::to_string(GetParam()) + R"(-byte allocation)");
Mitch Phillips78f06702021-06-01 14:35:43 -0700597 ASSERT_MATCH(result, R"((^|\s)allocated by thread .*
Peter Collingbournebbe69052020-05-08 10:11:19 -0700598 #00 pc)");
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700599 ASSERT_MATCH(result, "Memory tags around the fault address");
Peter Collingbournef8622522020-04-07 14:07:32 -0700600#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800601 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournef8622522020-04-07 14:07:32 -0700602#endif
603}
604
Florian Mayere6462f92024-02-28 11:12:11 -0800605__attribute__((noinline)) void mte_illegal_setjmp_helper(jmp_buf& jump_buf) {
Florian Mayer1fef1b12024-03-06 16:53:30 -0800606 // This frame is at least 8 bytes for storing and restoring the LR before the
607 // setjmp below. So this can never get an empty stack frame, even if we omit
608 // the frame pointer. So, the SP of this is always less (numerically) than the
609 // calling function frame.
Florian Mayere6462f92024-02-28 11:12:11 -0800610 setjmp(jump_buf);
611}
612
Florian Mayer92164902024-04-10 20:24:56 +0000613TEST_F(CrasherTest, DISABLED_mte_illegal_setjmp) {
Florian Mayere6462f92024-02-28 11:12:11 -0800614 // This setjmp is illegal because it jumps back into a function that already returned.
615 // Quoting man 3 setjmp:
616 // If the function which called setjmp() returns before longjmp() is
617 // called, the behavior is undefined. Some kind of subtle or
618 // unsubtle chaos is sure to result.
619 // https://man7.org/linux/man-pages/man3/longjmp.3.html
620#if defined(__aarch64__)
621 if (!mte_supported()) {
622 GTEST_SKIP() << "Requires MTE";
623 }
624
625 int intercept_result;
626 unique_fd output_fd;
627 StartProcess([&]() {
628 SetTagCheckingLevelSync();
629 jmp_buf jump_buf;
630 mte_illegal_setjmp_helper(jump_buf);
631 longjmp(jump_buf, 1);
632 });
633
634 StartIntercept(&output_fd);
635 FinishCrasher();
636 AssertDeath(SIGABRT);
637 FinishIntercept(&intercept_result);
638
639 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
640
641 std::string result;
642 ConsumeFd(std::move(output_fd), &result);
643
644 // In our test-case, we have a NEGATIVE stack adjustment, which is being
645 // interpreted as unsigned integer, and thus is "too large".
646 // TODO(fmayer): fix the error message for this
647 ASSERT_MATCH(result, R"(memtag_handle_longjmp: stack adjustment too large)");
648#else
649 GTEST_SKIP() << "Requires aarch64";
650#endif
651}
652
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800653TEST_F(CrasherTest, mte_async) {
654#if defined(__aarch64__)
655 if (!mte_supported()) {
656 GTEST_SKIP() << "Requires MTE";
657 }
658
659 int intercept_result;
660 unique_fd output_fd;
661 StartProcess([&]() {
662 SetTagCheckingLevelAsync();
663 volatile int* p = (volatile int*)malloc(16);
664 p[-1] = 42;
665 });
666
667 StartIntercept(&output_fd);
668 FinishCrasher();
669 AssertDeath(SIGSEGV);
670 FinishIntercept(&intercept_result);
671
672 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
673
674 std::string result;
675 ConsumeFd(std::move(output_fd), &result);
676
Peter Collingbourne91e816a2023-03-07 21:24:47 -0800677 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code [89] \(SEGV_MTE[AS]ERR\), fault addr)");
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800678#else
679 GTEST_SKIP() << "Requires aarch64";
680#endif
681}
682
Peter Collingbournef8622522020-04-07 14:07:32 -0700683TEST_F(CrasherTest, mte_multiple_causes) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800684#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700685 if (!mte_supported()) {
686 GTEST_SKIP() << "Requires MTE";
687 }
688
Mitch Phillips78f06702021-06-01 14:35:43 -0700689 LogcatCollector logcat_collector;
690
Peter Collingbournef8622522020-04-07 14:07:32 -0700691 int intercept_result;
692 unique_fd output_fd;
693 StartProcess([]() {
694 SetTagCheckingLevelSync();
695
696 // Make two allocations with the same tag and close to one another. Check for both properties
697 // with a bounds check -- this relies on the fact that only if the allocations have the same tag
698 // would they be measured as closer than 128 bytes to each other. Otherwise they would be about
699 // (some non-zero value << 56) apart.
700 //
701 // The out-of-bounds access will be considered either an overflow of one or an underflow of the
702 // other.
703 std::set<uintptr_t> allocs;
704 for (int i = 0; i != 4096; ++i) {
705 uintptr_t alloc = reinterpret_cast<uintptr_t>(malloc(16));
706 auto it = allocs.insert(alloc).first;
707 if (it != allocs.begin() && *std::prev(it) + 128 > alloc) {
708 *reinterpret_cast<int*>(*std::prev(it) + 16) = 42;
709 }
710 if (std::next(it) != allocs.end() && alloc + 128 > *std::next(it)) {
711 *reinterpret_cast<int*>(alloc + 16) = 42;
712 }
713 }
714 });
715
716 StartIntercept(&output_fd);
717 FinishCrasher();
718 AssertDeath(SIGSEGV);
719 FinishIntercept(&intercept_result);
720
721 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
722
Mitch Phillips78f06702021-06-01 14:35:43 -0700723 std::vector<std::string> log_sources(2);
724 ConsumeFd(std::move(output_fd), &log_sources[0]);
725 logcat_collector.Collect(&log_sources[1]);
Peter Collingbournef8622522020-04-07 14:07:32 -0700726
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700727 // Tag dump only in the tombstone, not logcat.
728 ASSERT_MATCH(log_sources[0], "Memory tags around the fault address");
729
Mitch Phillips78f06702021-06-01 14:35:43 -0700730 for (const auto& result : log_sources) {
731 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
732 ASSERT_THAT(result, HasSubstr("Note: multiple potential causes for this crash were detected, "
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800733 "listing them in decreasing order of likelihood."));
Mitch Phillips78f06702021-06-01 14:35:43 -0700734 // Adjacent untracked allocations may cause us to see the wrong underflow here (or only
735 // overflows), so we can't match explicitly for an underflow message.
736 ASSERT_MATCH(result,
737 R"(Cause: \[MTE\]: Buffer Overflow, 0 bytes right of a 16-byte allocation)");
738 // Ensure there's at least two allocation traces (one for each cause).
739 ASSERT_MATCH(
740 result,
741 R"((^|\s)allocated by thread .*?\n.*#00 pc(.|\n)*?(^|\s)allocated by thread .*?\n.*#00 pc)");
742 }
Peter Collingbournef8622522020-04-07 14:07:32 -0700743#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800744 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournef8622522020-04-07 14:07:32 -0700745#endif
746}
747
Peter Collingbournecd278072020-12-21 14:08:38 -0800748#if defined(__aarch64__)
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700749static uintptr_t CreateTagMapping() {
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700750 // Some of the MTE tag dump tests assert that there is an inaccessible page to the left and right
751 // of the PROT_MTE page, so map three pages and set the two guard pages to PROT_NONE.
752 size_t page_size = getpagesize();
753 void* mapping = mmap(nullptr, page_size * 3, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
754 uintptr_t mapping_uptr = reinterpret_cast<uintptr_t>(mapping);
755 if (mapping == MAP_FAILED) {
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700756 return 0;
757 }
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700758 mprotect(reinterpret_cast<void*>(mapping_uptr + page_size), page_size,
759 PROT_READ | PROT_WRITE | PROT_MTE);
760 // Stripe the mapping, where even granules get tag '1', and odd granules get tag '0'.
761 for (uintptr_t offset = 0; offset < page_size; offset += 2 * kTagGranuleSize) {
762 uintptr_t tagged_addr = mapping_uptr + page_size + offset + (1ULL << 56);
763 __asm__ __volatile__(".arch_extension mte; stg %0, [%0]" : : "r"(tagged_addr) : "memory");
764 }
765 return mapping_uptr + page_size;
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700766}
767#endif
768
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700769TEST_F(CrasherTest, mte_register_tag_dump) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800770#if defined(__aarch64__)
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700771 if (!mte_supported()) {
772 GTEST_SKIP() << "Requires MTE";
773 }
774
775 int intercept_result;
776 unique_fd output_fd;
777 StartProcess([&]() {
778 SetTagCheckingLevelSync();
779 Trap(reinterpret_cast<void *>(CreateTagMapping()));
780 });
781
782 StartIntercept(&output_fd);
783 FinishCrasher();
Evgenii Stepanov361455e2022-10-13 16:23:08 -0700784 AssertDeath(SIGSEGV);
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700785 FinishIntercept(&intercept_result);
786
787 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
788
789 std::string result;
790 ConsumeFd(std::move(output_fd), &result);
791
792 ASSERT_MATCH(result, R"(memory near x0:
793.*
794.*
795 01.............0 0000000000000000 0000000000000000 ................
796 00.............0)");
797#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800798 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700799#endif
800}
801
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700802TEST_F(CrasherTest, mte_fault_tag_dump_front_truncated) {
803#if defined(__aarch64__)
804 if (!mte_supported()) {
805 GTEST_SKIP() << "Requires MTE";
806 }
807
808 int intercept_result;
809 unique_fd output_fd;
810 StartProcess([&]() {
811 SetTagCheckingLevelSync();
812 volatile char* p = reinterpret_cast<char*>(CreateTagMapping());
813 p[0] = 0; // Untagged pointer, tagged memory.
814 });
815
816 StartIntercept(&output_fd);
817 FinishCrasher();
818 AssertDeath(SIGSEGV);
819 FinishIntercept(&intercept_result);
820
821 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
822
823 std::string result;
824 ConsumeFd(std::move(output_fd), &result);
825
826 ASSERT_MATCH(result, R"(Memory tags around the fault address.*
827\s*=>0x[0-9a-f]+000:\[1\] 0 1 0)");
828#else
829 GTEST_SKIP() << "Requires aarch64";
830#endif
831}
832
833TEST_F(CrasherTest, mte_fault_tag_dump) {
834#if defined(__aarch64__)
835 if (!mte_supported()) {
836 GTEST_SKIP() << "Requires MTE";
837 }
838
839 int intercept_result;
840 unique_fd output_fd;
841 StartProcess([&]() {
842 SetTagCheckingLevelSync();
843 volatile char* p = reinterpret_cast<char*>(CreateTagMapping());
844 p[320] = 0; // Untagged pointer, tagged memory.
845 });
846
847 StartIntercept(&output_fd);
848 FinishCrasher();
849 AssertDeath(SIGSEGV);
850 FinishIntercept(&intercept_result);
851
852 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
853
854 std::string result;
855 ConsumeFd(std::move(output_fd), &result);
856
857 ASSERT_MATCH(result, R"(Memory tags around the fault address.*
858\s*0x[0-9a-f]+: 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
859\s*=>0x[0-9a-f]+: 1 0 1 0 \[1\] 0 1 0 1 0 1 0 1 0 1 0
860\s*0x[0-9a-f]+: 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
861)");
862#else
863 GTEST_SKIP() << "Requires aarch64";
864#endif
865}
866
867TEST_F(CrasherTest, mte_fault_tag_dump_rear_truncated) {
868#if defined(__aarch64__)
869 if (!mte_supported()) {
870 GTEST_SKIP() << "Requires MTE";
871 }
872
873 int intercept_result;
874 unique_fd output_fd;
875 StartProcess([&]() {
876 SetTagCheckingLevelSync();
877 size_t page_size = getpagesize();
878 volatile char* p = reinterpret_cast<char*>(CreateTagMapping());
879 p[page_size - kTagGranuleSize * 2] = 0; // Untagged pointer, tagged memory.
880 });
881
882 StartIntercept(&output_fd);
883 FinishCrasher();
884 AssertDeath(SIGSEGV);
885 FinishIntercept(&intercept_result);
886
887 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
888
889 std::string result;
890 ConsumeFd(std::move(output_fd), &result);
891
892 ASSERT_MATCH(result, R"(Memory tags around the fault address)");
893 ASSERT_MATCH(result,
894 R"(\s*0x[0-9a-f]+: 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
895\s*=>0x[0-9a-f]+: 1 0 1 0 1 0 1 0 1 0 1 0 1 0 \[1\] 0
896
897)"); // Ensure truncation happened and there's a newline after the tag fault.
898#else
899 GTEST_SKIP() << "Requires aarch64";
900#endif
901}
902
Josh Gaocdea7502017-11-01 15:00:40 -0700903TEST_F(CrasherTest, LD_PRELOAD) {
904 int intercept_result;
905 unique_fd output_fd;
906 StartProcess([]() {
907 setenv("LD_PRELOAD", "nonexistent.so", 1);
908 *reinterpret_cast<volatile char*>(0xdead) = '1';
909 });
910
911 StartIntercept(&output_fd);
912 FinishCrasher();
913 AssertDeath(SIGSEGV);
914 FinishIntercept(&intercept_result);
915
916 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
917
918 std::string result;
919 ConsumeFd(std::move(output_fd), &result);
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800920 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+dead)");
Josh Gaocdea7502017-11-01 15:00:40 -0700921}
922
Josh Gaocbe70cb2016-10-18 18:17:52 -0700923TEST_F(CrasherTest, abort) {
924 int intercept_result;
925 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -0800926 StartProcess([]() {
927 abort();
928 });
Josh Gaocbe70cb2016-10-18 18:17:52 -0700929 StartIntercept(&output_fd);
930 FinishCrasher();
931 AssertDeath(SIGABRT);
932 FinishIntercept(&intercept_result);
933
934 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
935
936 std::string result;
937 ConsumeFd(std::move(output_fd), &result);
Andreas Gampe26cbafb2017-06-22 20:14:43 -0700938 ASSERT_BACKTRACE_FRAME(result, "abort");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700939}
940
941TEST_F(CrasherTest, signal) {
942 int intercept_result;
943 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -0800944 StartProcess([]() {
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700945 while (true) {
946 sleep(1);
947 }
Josh Gao502cfd22017-02-17 01:39:15 -0800948 });
Josh Gaocbe70cb2016-10-18 18:17:52 -0700949 StartIntercept(&output_fd);
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700950 FinishCrasher();
Josh Gaocbe70cb2016-10-18 18:17:52 -0700951 ASSERT_EQ(0, kill(crasher_pid, SIGSEGV));
952
953 AssertDeath(SIGSEGV);
954 FinishIntercept(&intercept_result);
955
956 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
957
958 std::string result;
959 ConsumeFd(std::move(output_fd), &result);
Elliott Hughes89722702018-05-02 10:47:00 -0700960 ASSERT_MATCH(
961 result,
962 R"(signal 11 \(SIGSEGV\), code 0 \(SI_USER from pid \d+, uid \d+\), fault addr --------)");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700963 ASSERT_MATCH(result, R"(backtrace:)");
964}
965
966TEST_F(CrasherTest, abort_message) {
967 int intercept_result;
968 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -0800969 StartProcess([]() {
Josh Gao1cc7bd82018-02-13 13:16:17 -0800970 // Arrived at experimentally;
971 // logd truncates at 4062.
972 // strlen("Abort message: ''") is 17.
973 // That's 4045, but we also want a NUL.
974 char buf[4045 + 1];
975 memset(buf, 'x', sizeof(buf));
976 buf[sizeof(buf) - 1] = '\0';
977 android_set_abort_message(buf);
Josh Gao502cfd22017-02-17 01:39:15 -0800978 abort();
979 });
Josh Gaocbe70cb2016-10-18 18:17:52 -0700980 StartIntercept(&output_fd);
981 FinishCrasher();
982 AssertDeath(SIGABRT);
983 FinishIntercept(&intercept_result);
984
985 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
986
987 std::string result;
988 ConsumeFd(std::move(output_fd), &result);
Josh Gao1cc7bd82018-02-13 13:16:17 -0800989 ASSERT_MATCH(result, R"(Abort message: 'x{4045}')");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700990}
991
Florian Mayer5fa66632024-02-07 16:42:23 -0800992static char g_crash_detail_value_changes[] = "crash_detail_value";
993static char g_crash_detail_value[] = "crash_detail_value";
994static char g_crash_detail_value2[] = "crash_detail_value2";
995
996inline crash_detail_t* _Nullable android_register_crash_detail_strs(const char* _Nonnull name,
997 const char* _Nonnull data) {
Florian Mayer920d95b2024-02-14 12:57:09 -0800998 return android_crash_detail_register(name, strlen(name), data, strlen(data));
Florian Mayer5fa66632024-02-07 16:42:23 -0800999}
1000
1001TEST_F(CrasherTest, crash_detail_single) {
1002 int intercept_result;
1003 unique_fd output_fd;
1004 StartProcess([]() {
1005 android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value);
1006 abort();
1007 });
1008 StartIntercept(&output_fd);
1009 FinishCrasher();
1010 AssertDeath(SIGABRT);
1011 FinishIntercept(&intercept_result);
1012
1013 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1014
1015 std::string result;
1016 ConsumeFd(std::move(output_fd), &result);
1017 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'crash_detail_value')");
1018}
1019
Florian Mayeraced3aa2024-02-13 13:44:50 -08001020TEST_F(CrasherTest, crash_detail_replace_data) {
1021 int intercept_result;
1022 unique_fd output_fd;
1023 StartProcess([]() {
1024 auto *cd = android_register_crash_detail_strs("CRASH_DETAIL_NAME", "original_data");
Florian Mayer920d95b2024-02-14 12:57:09 -08001025 android_crash_detail_replace_data(cd, "new_data", strlen("new_data"));
Florian Mayeraced3aa2024-02-13 13:44:50 -08001026 abort();
1027 });
1028 StartIntercept(&output_fd);
1029 FinishCrasher();
1030 AssertDeath(SIGABRT);
1031 FinishIntercept(&intercept_result);
1032
1033 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1034
1035 std::string result;
1036 ConsumeFd(std::move(output_fd), &result);
1037 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'new_data')");
1038 // Ensure the old one no longer shows up, i.e. that we actually replaced
1039 // it, not added a new one.
1040 ASSERT_NOT_MATCH(result, R"(CRASH_DETAIL_NAME: 'original_data')");
1041}
1042
1043TEST_F(CrasherTest, crash_detail_replace_name) {
1044 int intercept_result;
1045 unique_fd output_fd;
1046 StartProcess([]() {
1047 auto *cd = android_register_crash_detail_strs("old_name", g_crash_detail_value);
Florian Mayer920d95b2024-02-14 12:57:09 -08001048 android_crash_detail_replace_name(cd, "new_name", strlen("new_name"));
Florian Mayeraced3aa2024-02-13 13:44:50 -08001049 abort();
1050 });
1051 StartIntercept(&output_fd);
1052 FinishCrasher();
1053 AssertDeath(SIGABRT);
1054 FinishIntercept(&intercept_result);
1055
1056 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1057
1058 std::string result;
1059 ConsumeFd(std::move(output_fd), &result);
1060 ASSERT_MATCH(result, R"(new_name: 'crash_detail_value')");
1061 // Ensure the old one no longer shows up, i.e. that we actually replaced
1062 // it, not added a new one.
1063 ASSERT_NOT_MATCH(result, R"(old_name: 'crash_detail_value')");
1064}
1065
Florian Mayer5fa66632024-02-07 16:42:23 -08001066TEST_F(CrasherTest, crash_detail_single_byte_name) {
1067 int intercept_result;
1068 unique_fd output_fd;
1069 StartProcess([]() {
1070 android_register_crash_detail_strs("CRASH_DETAIL_NAME\1", g_crash_detail_value);
1071 abort();
1072 });
1073 StartIntercept(&output_fd);
1074 FinishCrasher();
1075 AssertDeath(SIGABRT);
1076 FinishIntercept(&intercept_result);
1077
1078 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1079
1080 std::string result;
1081 ConsumeFd(std::move(output_fd), &result);
1082 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME\\1: 'crash_detail_value')");
1083}
1084
1085
1086TEST_F(CrasherTest, crash_detail_single_bytes) {
1087 int intercept_result;
1088 unique_fd output_fd;
1089 StartProcess([]() {
Florian Mayer920d95b2024-02-14 12:57:09 -08001090 android_crash_detail_register("CRASH_DETAIL_NAME", strlen("CRASH_DETAIL_NAME"), "\1",
Florian Mayer5fa66632024-02-07 16:42:23 -08001091 sizeof("\1"));
1092 abort();
1093 });
1094 StartIntercept(&output_fd);
1095 FinishCrasher();
1096 AssertDeath(SIGABRT);
1097 FinishIntercept(&intercept_result);
1098
1099 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1100
1101 std::string result;
1102 ConsumeFd(std::move(output_fd), &result);
1103 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: '\\1\\0')");
1104}
1105
1106TEST_F(CrasherTest, crash_detail_mixed) {
1107 int intercept_result;
1108 unique_fd output_fd;
1109 StartProcess([]() {
1110 const char data[] = "helloworld\1\255\3";
1111 android_register_crash_detail_strs("CRASH_DETAIL_NAME", data);
1112 abort();
1113 });
1114 StartIntercept(&output_fd);
1115 FinishCrasher();
1116 AssertDeath(SIGABRT);
1117 FinishIntercept(&intercept_result);
1118
1119 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1120
1121 std::string result;
1122 ConsumeFd(std::move(output_fd), &result);
1123 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'helloworld\\1\\255\\3')");
1124}
1125
1126TEST_F(CrasherTest, crash_detail_many) {
1127 int intercept_result;
1128 unique_fd output_fd;
1129 StartProcess([]() {
1130 for (int i = 0; i < 1000; ++i) {
1131 std::string name = "CRASH_DETAIL_NAME" + std::to_string(i);
1132 std::string value = "CRASH_DETAIL_VALUE" + std::to_string(i);
1133 auto* h = android_register_crash_detail_strs(name.data(), value.data());
Florian Mayer920d95b2024-02-14 12:57:09 -08001134 android_crash_detail_unregister(h);
Florian Mayer5fa66632024-02-07 16:42:23 -08001135 }
1136
1137 android_register_crash_detail_strs("FINAL_NAME", "FINAL_VALUE");
1138 android_register_crash_detail_strs("FINAL_NAME2", "FINAL_VALUE2");
1139 abort();
1140 });
1141 StartIntercept(&output_fd);
1142 FinishCrasher();
1143 AssertDeath(SIGABRT);
1144 FinishIntercept(&intercept_result);
1145
1146 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1147
1148 std::string result;
1149 ConsumeFd(std::move(output_fd), &result);
1150 ASSERT_NOT_MATCH(result, "CRASH_DETAIL_NAME");
1151 ASSERT_NOT_MATCH(result, "CRASH_DETAIL_VALUE");
1152 ASSERT_MATCH(result, R"(FINAL_NAME: 'FINAL_VALUE')");
1153 ASSERT_MATCH(result, R"(FINAL_NAME2: 'FINAL_VALUE2')");
1154}
1155
1156TEST_F(CrasherTest, crash_detail_single_changes) {
1157 int intercept_result;
1158 unique_fd output_fd;
1159 StartProcess([]() {
1160 android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value_changes);
1161 g_crash_detail_value_changes[0] = 'C';
1162 abort();
1163 });
1164 StartIntercept(&output_fd);
1165 FinishCrasher();
1166 AssertDeath(SIGABRT);
1167 FinishIntercept(&intercept_result);
1168
1169 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1170
1171 std::string result;
1172 ConsumeFd(std::move(output_fd), &result);
1173 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'Crash_detail_value')");
1174}
1175
1176TEST_F(CrasherTest, crash_detail_multiple) {
1177 int intercept_result;
1178 unique_fd output_fd;
1179 StartProcess([]() {
1180 android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value);
1181 android_register_crash_detail_strs("CRASH_DETAIL_NAME2", g_crash_detail_value2);
1182 abort();
1183 });
1184 StartIntercept(&output_fd);
1185 FinishCrasher();
1186 AssertDeath(SIGABRT);
1187 FinishIntercept(&intercept_result);
1188
1189 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1190
1191 std::string result;
1192 ConsumeFd(std::move(output_fd), &result);
1193 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'crash_detail_value')");
1194 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME2: 'crash_detail_value2')");
1195}
1196
1197TEST_F(CrasherTest, crash_detail_remove) {
1198 int intercept_result;
1199 unique_fd output_fd;
1200 StartProcess([]() {
1201 auto* detail1 = android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value);
Florian Mayer920d95b2024-02-14 12:57:09 -08001202 android_crash_detail_unregister(detail1);
Florian Mayer5fa66632024-02-07 16:42:23 -08001203 android_register_crash_detail_strs("CRASH_DETAIL_NAME2", g_crash_detail_value2);
1204 abort();
1205 });
1206 StartIntercept(&output_fd);
1207 FinishCrasher();
1208 AssertDeath(SIGABRT);
1209 FinishIntercept(&intercept_result);
1210
1211 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1212
1213 std::string result;
1214 ConsumeFd(std::move(output_fd), &result);
1215 ASSERT_NOT_MATCH(result, R"(CRASH_DETAIL_NAME: 'crash_detail_value')");
1216 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME2: 'crash_detail_value2')");
1217}
1218
Christopher Ferrise8891452021-08-17 17:34:53 -07001219TEST_F(CrasherTest, abort_message_newline_trimmed) {
1220 int intercept_result;
1221 unique_fd output_fd;
1222 StartProcess([]() {
1223 android_set_abort_message("Message with a newline.\n");
1224 abort();
1225 });
1226 StartIntercept(&output_fd);
1227 FinishCrasher();
1228 AssertDeath(SIGABRT);
1229 FinishIntercept(&intercept_result);
1230
1231 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1232
1233 std::string result;
1234 ConsumeFd(std::move(output_fd), &result);
1235 ASSERT_MATCH(result, R"(Abort message: 'Message with a newline.')");
1236}
1237
1238TEST_F(CrasherTest, abort_message_multiple_newlines_trimmed) {
1239 int intercept_result;
1240 unique_fd output_fd;
1241 StartProcess([]() {
1242 android_set_abort_message("Message with multiple newlines.\n\n\n\n\n");
1243 abort();
1244 });
1245 StartIntercept(&output_fd);
1246 FinishCrasher();
1247 AssertDeath(SIGABRT);
1248 FinishIntercept(&intercept_result);
1249
1250 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1251
1252 std::string result;
1253 ConsumeFd(std::move(output_fd), &result);
1254 ASSERT_MATCH(result, R"(Abort message: 'Message with multiple newlines.')");
1255}
1256
Josh Gaoe06f2a42017-04-27 16:50:38 -07001257TEST_F(CrasherTest, abort_message_backtrace) {
1258 int intercept_result;
1259 unique_fd output_fd;
1260 StartProcess([]() {
1261 android_set_abort_message("not actually aborting");
Josh Gaoa48b41b2019-12-13 14:11:04 -08001262 raise(BIONIC_SIGNAL_DEBUGGER);
Josh Gaoe06f2a42017-04-27 16:50:38 -07001263 exit(0);
1264 });
1265 StartIntercept(&output_fd);
1266 FinishCrasher();
1267 AssertDeath(0);
1268 FinishIntercept(&intercept_result);
1269
1270 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1271
1272 std::string result;
1273 ConsumeFd(std::move(output_fd), &result);
1274 ASSERT_NOT_MATCH(result, R"(Abort message:)");
1275}
1276
Josh Gaocbe70cb2016-10-18 18:17:52 -07001277TEST_F(CrasherTest, intercept_timeout) {
1278 int intercept_result;
1279 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -08001280 StartProcess([]() {
1281 abort();
1282 });
Josh Gaocbe70cb2016-10-18 18:17:52 -07001283 StartIntercept(&output_fd);
1284
1285 // Don't let crasher finish until we timeout.
1286 FinishIntercept(&intercept_result);
1287
1288 ASSERT_NE(1, intercept_result) << "tombstoned reported success? (intercept_result = "
1289 << intercept_result << ")";
1290
1291 FinishCrasher();
1292 AssertDeath(SIGABRT);
1293}
1294
Elliott Hughese4781d52021-03-17 09:15:15 -07001295TEST_F(CrasherTest, wait_for_debugger) {
1296 if (!android::base::SetProperty(kWaitForDebuggerKey, "1")) {
1297 FAIL() << "failed to enable wait_for_debugger";
Josh Gaocbe70cb2016-10-18 18:17:52 -07001298 }
1299 sleep(1);
1300
Josh Gao502cfd22017-02-17 01:39:15 -08001301 StartProcess([]() {
1302 abort();
1303 });
Josh Gaocbe70cb2016-10-18 18:17:52 -07001304 FinishCrasher();
1305
1306 int status;
Christopher Ferris172b0a02019-09-18 17:48:30 -07001307 ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, WUNTRACED)));
Josh Gaocbe70cb2016-10-18 18:17:52 -07001308 ASSERT_TRUE(WIFSTOPPED(status));
1309 ASSERT_EQ(SIGSTOP, WSTOPSIG(status));
1310
1311 ASSERT_EQ(0, kill(crasher_pid, SIGCONT));
1312
1313 AssertDeath(SIGABRT);
1314}
1315
Josh Gaocbe70cb2016-10-18 18:17:52 -07001316TEST_F(CrasherTest, backtrace) {
1317 std::string result;
1318 int intercept_result;
1319 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -08001320
1321 StartProcess([]() {
1322 abort();
1323 });
Narayan Kamatha73df602017-05-24 15:07:25 +01001324 StartIntercept(&output_fd, kDebuggerdNativeBacktrace);
Josh Gaocbe70cb2016-10-18 18:17:52 -07001325
1326 std::this_thread::sleep_for(500ms);
1327
1328 sigval val;
1329 val.sival_int = 1;
Josh Gaoa48b41b2019-12-13 14:11:04 -08001330 ASSERT_EQ(0, sigqueue(crasher_pid, BIONIC_SIGNAL_DEBUGGER, val)) << strerror(errno);
Josh Gaocbe70cb2016-10-18 18:17:52 -07001331 FinishIntercept(&intercept_result);
1332 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1333 ConsumeFd(std::move(output_fd), &result);
Jaesung Chung58778e12017-06-15 18:20:34 +09001334 ASSERT_BACKTRACE_FRAME(result, "read");
Josh Gaocbe70cb2016-10-18 18:17:52 -07001335
1336 int status;
1337 ASSERT_EQ(0, waitpid(crasher_pid, &status, WNOHANG | WUNTRACED));
1338
1339 StartIntercept(&output_fd);
1340 FinishCrasher();
1341 AssertDeath(SIGABRT);
1342 FinishIntercept(&intercept_result);
1343 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1344 ConsumeFd(std::move(output_fd), &result);
Andreas Gampe26cbafb2017-06-22 20:14:43 -07001345 ASSERT_BACKTRACE_FRAME(result, "abort");
Josh Gaocbe70cb2016-10-18 18:17:52 -07001346}
Josh Gaofca7ca32017-01-23 12:05:35 -08001347
1348TEST_F(CrasherTest, PR_SET_DUMPABLE_0_crash) {
Josh Gao502cfd22017-02-17 01:39:15 -08001349 int intercept_result;
1350 unique_fd output_fd;
Josh Gaofca7ca32017-01-23 12:05:35 -08001351 StartProcess([]() {
1352 prctl(PR_SET_DUMPABLE, 0);
Josh Gao502cfd22017-02-17 01:39:15 -08001353 abort();
Josh Gaofca7ca32017-01-23 12:05:35 -08001354 });
Josh Gao502cfd22017-02-17 01:39:15 -08001355
1356 StartIntercept(&output_fd);
1357 FinishCrasher();
1358 AssertDeath(SIGABRT);
1359 FinishIntercept(&intercept_result);
1360
1361 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1362
1363 std::string result;
1364 ConsumeFd(std::move(output_fd), &result);
Andreas Gampe26cbafb2017-06-22 20:14:43 -07001365 ASSERT_BACKTRACE_FRAME(result, "abort");
Josh Gaofca7ca32017-01-23 12:05:35 -08001366}
1367
Josh Gao502cfd22017-02-17 01:39:15 -08001368TEST_F(CrasherTest, capabilities) {
1369 ASSERT_EQ(0U, getuid()) << "capability test requires root";
1370
Josh Gaofca7ca32017-01-23 12:05:35 -08001371 StartProcess([]() {
Josh Gao502cfd22017-02-17 01:39:15 -08001372 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
1373 err(1, "failed to set PR_SET_KEEPCAPS");
1374 }
1375
1376 if (setresuid(1, 1, 1) != 0) {
1377 err(1, "setresuid failed");
1378 }
1379
1380 __user_cap_header_struct capheader;
1381 __user_cap_data_struct capdata[2];
1382 memset(&capheader, 0, sizeof(capheader));
1383 memset(&capdata, 0, sizeof(capdata));
1384
1385 capheader.version = _LINUX_CAPABILITY_VERSION_3;
1386 capheader.pid = 0;
1387
1388 // Turn on every third capability.
1389 static_assert(CAP_LAST_CAP > 33, "CAP_LAST_CAP <= 32");
1390 for (int i = 0; i < CAP_LAST_CAP; i += 3) {
1391 capdata[CAP_TO_INDEX(i)].permitted |= CAP_TO_MASK(i);
1392 capdata[CAP_TO_INDEX(i)].effective |= CAP_TO_MASK(i);
1393 }
1394
1395 // Make sure CAP_SYS_PTRACE is off.
1396 capdata[CAP_TO_INDEX(CAP_SYS_PTRACE)].permitted &= ~(CAP_TO_MASK(CAP_SYS_PTRACE));
1397 capdata[CAP_TO_INDEX(CAP_SYS_PTRACE)].effective &= ~(CAP_TO_MASK(CAP_SYS_PTRACE));
1398
1399 if (capset(&capheader, &capdata[0]) != 0) {
1400 err(1, "capset failed");
1401 }
1402
1403 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0) != 0) {
1404 err(1, "failed to drop ambient capabilities");
1405 }
1406
Josh Gaoa5199a92017-04-03 13:18:34 -07001407 pthread_setname_np(pthread_self(), "thread_name");
Josh Gao502cfd22017-02-17 01:39:15 -08001408 raise(SIGSYS);
Josh Gaofca7ca32017-01-23 12:05:35 -08001409 });
Josh Gao502cfd22017-02-17 01:39:15 -08001410
1411 unique_fd output_fd;
1412 StartIntercept(&output_fd);
1413 FinishCrasher();
1414 AssertDeath(SIGSYS);
1415
1416 std::string result;
1417 int intercept_result;
1418 FinishIntercept(&intercept_result);
1419 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1420 ConsumeFd(std::move(output_fd), &result);
Josh Gaoa5199a92017-04-03 13:18:34 -07001421 ASSERT_MATCH(result, R"(name: thread_name\s+>>> .+debuggerd_test(32|64) <<<)");
Jaesung Chung58778e12017-06-15 18:20:34 +09001422 ASSERT_BACKTRACE_FRAME(result, "tgkill");
Josh Gaofca7ca32017-01-23 12:05:35 -08001423}
Josh Gaoc3c8c022017-02-13 16:36:18 -08001424
Josh Gao2e7b8e22017-05-04 17:12:57 -07001425TEST_F(CrasherTest, fake_pid) {
1426 int intercept_result;
1427 unique_fd output_fd;
1428
1429 // Prime the getpid/gettid caches.
1430 UNUSED(getpid());
1431 UNUSED(gettid());
1432
1433 std::function<pid_t()> clone_fn = []() {
1434 return syscall(__NR_clone, SIGCHLD, nullptr, nullptr, nullptr, nullptr);
1435 };
1436 StartProcess(
1437 []() {
1438 ASSERT_NE(getpid(), syscall(__NR_getpid));
1439 ASSERT_NE(gettid(), syscall(__NR_gettid));
1440 raise(SIGSEGV);
1441 },
1442 clone_fn);
1443
1444 StartIntercept(&output_fd);
1445 FinishCrasher();
1446 AssertDeath(SIGSEGV);
1447 FinishIntercept(&intercept_result);
1448
1449 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1450
1451 std::string result;
1452 ConsumeFd(std::move(output_fd), &result);
Jaesung Chung58778e12017-06-15 18:20:34 +09001453 ASSERT_BACKTRACE_FRAME(result, "tgkill");
Josh Gao2e7b8e22017-05-04 17:12:57 -07001454}
1455
Josh Gaoe04ca272018-01-16 15:38:17 -08001456static const char* const kDebuggerdSeccompPolicy =
1457 "/system/etc/seccomp_policy/crash_dump." ABI_STRING ".policy";
1458
Mitch Phillips18ce5422023-01-19 14:23:49 -08001459static void setup_jail(minijail* jail) {
1460 if (!jail) {
1461 LOG(FATAL) << "failed to create minijail";
1462 }
1463
Josh Gao6f9eeec2018-09-12 13:55:47 -07001464 std::string policy;
1465 if (!android::base::ReadFileToString(kDebuggerdSeccompPolicy, &policy)) {
1466 PLOG(FATAL) << "failed to read policy file";
1467 }
1468
1469 // Allow a bunch of syscalls used by the tests.
1470 policy += "\nclone: 1";
1471 policy += "\nsigaltstack: 1";
1472 policy += "\nnanosleep: 1";
Christopher Ferrisab606682019-09-17 15:31:47 -07001473 policy += "\ngetrlimit: 1";
1474 policy += "\nugetrlimit: 1";
Josh Gao6f9eeec2018-09-12 13:55:47 -07001475
1476 FILE* tmp_file = tmpfile();
1477 if (!tmp_file) {
1478 PLOG(FATAL) << "tmpfile failed";
1479 }
1480
Christopher Ferris172b0a02019-09-18 17:48:30 -07001481 unique_fd tmp_fd(TEMP_FAILURE_RETRY(dup(fileno(tmp_file))));
Josh Gao6f9eeec2018-09-12 13:55:47 -07001482 if (!android::base::WriteStringToFd(policy, tmp_fd.get())) {
1483 PLOG(FATAL) << "failed to write policy to tmpfile";
1484 }
1485
1486 if (lseek(tmp_fd.get(), 0, SEEK_SET) != 0) {
1487 PLOG(FATAL) << "failed to seek tmp_fd";
Josh Gaoe04ca272018-01-16 15:38:17 -08001488 }
1489
Mitch Phillips18ce5422023-01-19 14:23:49 -08001490 minijail_no_new_privs(jail);
1491 minijail_log_seccomp_filter_failures(jail);
1492 minijail_use_seccomp_filter(jail);
1493 minijail_parse_seccomp_filters_from_fd(jail, tmp_fd.release());
1494}
Josh Gaoe04ca272018-01-16 15:38:17 -08001495
Mitch Phillips18ce5422023-01-19 14:23:49 -08001496static pid_t seccomp_fork_impl(void (*prejail)()) {
1497 ScopedMinijail jail{minijail_new()};
1498 setup_jail(jail.get());
Josh Gaoe04ca272018-01-16 15:38:17 -08001499
1500 pid_t result = fork();
1501 if (result == -1) {
1502 return result;
1503 } else if (result != 0) {
1504 return result;
1505 }
1506
1507 // Spawn and detach a thread that spins forever.
1508 std::atomic<bool> thread_ready(false);
1509 std::thread thread([&jail, &thread_ready]() {
1510 minijail_enter(jail.get());
1511 thread_ready = true;
1512 for (;;)
1513 ;
1514 });
1515 thread.detach();
1516
1517 while (!thread_ready) {
1518 continue;
1519 }
1520
Josh Gao70adac62018-02-22 11:38:33 -08001521 if (prejail) {
1522 prejail();
1523 }
1524
Josh Gaoe04ca272018-01-16 15:38:17 -08001525 minijail_enter(jail.get());
1526 return result;
1527}
1528
Josh Gao70adac62018-02-22 11:38:33 -08001529static pid_t seccomp_fork() {
1530 return seccomp_fork_impl(nullptr);
1531}
1532
Josh Gaoe04ca272018-01-16 15:38:17 -08001533TEST_F(CrasherTest, seccomp_crash) {
1534 int intercept_result;
1535 unique_fd output_fd;
1536
1537 StartProcess([]() { abort(); }, &seccomp_fork);
1538
1539 StartIntercept(&output_fd);
1540 FinishCrasher();
1541 AssertDeath(SIGABRT);
1542 FinishIntercept(&intercept_result);
1543 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1544
1545 std::string result;
1546 ConsumeFd(std::move(output_fd), &result);
1547 ASSERT_BACKTRACE_FRAME(result, "abort");
1548}
1549
Josh Gao70adac62018-02-22 11:38:33 -08001550static pid_t seccomp_fork_rlimit() {
1551 return seccomp_fork_impl([]() {
1552 struct rlimit rlim = {
1553 .rlim_cur = 512 * 1024 * 1024,
1554 .rlim_max = 512 * 1024 * 1024,
1555 };
1556
1557 if (setrlimit(RLIMIT_AS, &rlim) != 0) {
1558 raise(SIGINT);
1559 }
1560 });
1561}
1562
1563TEST_F(CrasherTest, seccomp_crash_oom) {
1564 int intercept_result;
1565 unique_fd output_fd;
1566
1567 StartProcess(
1568 []() {
1569 std::vector<void*> vec;
1570 for (int i = 0; i < 512; ++i) {
1571 char* buf = static_cast<char*>(malloc(1024 * 1024));
1572 if (!buf) {
1573 abort();
1574 }
1575 memset(buf, 0xff, 1024 * 1024);
1576 vec.push_back(buf);
1577 }
1578 },
1579 &seccomp_fork_rlimit);
1580
1581 StartIntercept(&output_fd);
1582 FinishCrasher();
1583 AssertDeath(SIGABRT);
1584 FinishIntercept(&intercept_result);
1585 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1586
1587 // We can't actually generate a backtrace, just make sure that the process terminates.
1588}
1589
Elliott Hughesb795d6f2022-09-14 20:15:19 +00001590__attribute__((__noinline__)) extern "C" bool raise_debugger_signal(DebuggerdDumpType dump_type) {
Josh Gaoe04ca272018-01-16 15:38:17 -08001591 siginfo_t siginfo;
1592 siginfo.si_code = SI_QUEUE;
1593 siginfo.si_pid = getpid();
1594 siginfo.si_uid = getuid();
1595
1596 if (dump_type != kDebuggerdNativeBacktrace && dump_type != kDebuggerdTombstone) {
1597 PLOG(FATAL) << "invalid dump type";
1598 }
1599
1600 siginfo.si_value.sival_int = dump_type == kDebuggerdNativeBacktrace;
1601
Josh Gaoa48b41b2019-12-13 14:11:04 -08001602 if (syscall(__NR_rt_tgsigqueueinfo, getpid(), gettid(), BIONIC_SIGNAL_DEBUGGER, &siginfo) != 0) {
Josh Gaoe04ca272018-01-16 15:38:17 -08001603 PLOG(ERROR) << "libdebuggerd_client: failed to send signal to self";
1604 return false;
1605 }
1606
1607 return true;
1608}
1609
Christopher Ferrisb999b822022-02-09 17:57:21 -08001610extern "C" void foo() {
1611 LOG(INFO) << "foo";
1612 std::this_thread::sleep_for(1s);
1613}
1614
1615extern "C" void bar() {
1616 LOG(INFO) << "bar";
1617 std::this_thread::sleep_for(1s);
1618}
1619
Josh Gaoe04ca272018-01-16 15:38:17 -08001620TEST_F(CrasherTest, seccomp_tombstone) {
1621 int intercept_result;
1622 unique_fd output_fd;
1623
1624 static const auto dump_type = kDebuggerdTombstone;
1625 StartProcess(
1626 []() {
Christopher Ferrisb999b822022-02-09 17:57:21 -08001627 std::thread a(foo);
1628 std::thread b(bar);
1629
1630 std::this_thread::sleep_for(100ms);
1631
Josh Gaoe04ca272018-01-16 15:38:17 -08001632 raise_debugger_signal(dump_type);
1633 _exit(0);
1634 },
1635 &seccomp_fork);
1636
1637 StartIntercept(&output_fd, dump_type);
1638 FinishCrasher();
1639 AssertDeath(0);
1640 FinishIntercept(&intercept_result);
1641 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1642
1643 std::string result;
1644 ConsumeFd(std::move(output_fd), &result);
1645 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
Christopher Ferrisb999b822022-02-09 17:57:21 -08001646 ASSERT_BACKTRACE_FRAME(result, "foo");
1647 ASSERT_BACKTRACE_FRAME(result, "bar");
Josh Gao6f9eeec2018-09-12 13:55:47 -07001648}
1649
Christopher Ferris303c6be2022-05-24 17:08:33 -07001650TEST_F(CrasherTest, seccomp_tombstone_thread_abort) {
1651 int intercept_result;
1652 unique_fd output_fd;
1653
1654 static const auto dump_type = kDebuggerdTombstone;
1655 StartProcess(
1656 []() {
1657 std::thread abort_thread([] { abort(); });
1658 abort_thread.join();
1659 },
1660 &seccomp_fork);
1661
1662 StartIntercept(&output_fd, dump_type);
1663 FinishCrasher();
1664 AssertDeath(SIGABRT);
1665 FinishIntercept(&intercept_result);
1666 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1667
1668 std::string result;
1669 ConsumeFd(std::move(output_fd), &result);
1670 ASSERT_BACKTRACE_FRAME(result, "abort");
1671}
1672
Christopher Ferris7c2e7e32022-05-27 12:57:58 -07001673TEST_F(CrasherTest, seccomp_tombstone_multiple_threads_abort) {
1674 int intercept_result;
1675 unique_fd output_fd;
1676
1677 static const auto dump_type = kDebuggerdTombstone;
1678 StartProcess(
1679 []() {
1680 std::thread a(foo);
1681 std::thread b(bar);
1682
1683 std::this_thread::sleep_for(100ms);
1684
1685 std::thread abort_thread([] { abort(); });
1686 abort_thread.join();
1687 },
1688 &seccomp_fork);
1689
1690 StartIntercept(&output_fd, dump_type);
1691 FinishCrasher();
1692 AssertDeath(SIGABRT);
1693 FinishIntercept(&intercept_result);
1694 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1695
1696 std::string result;
1697 ConsumeFd(std::move(output_fd), &result);
1698 ASSERT_BACKTRACE_FRAME(result, "abort");
1699 ASSERT_BACKTRACE_FRAME(result, "foo");
1700 ASSERT_BACKTRACE_FRAME(result, "bar");
1701 ASSERT_BACKTRACE_FRAME(result, "main");
1702}
1703
Josh Gaoe04ca272018-01-16 15:38:17 -08001704TEST_F(CrasherTest, seccomp_backtrace) {
1705 int intercept_result;
1706 unique_fd output_fd;
1707
1708 static const auto dump_type = kDebuggerdNativeBacktrace;
1709 StartProcess(
1710 []() {
Josh Gao6f9eeec2018-09-12 13:55:47 -07001711 std::thread a(foo);
1712 std::thread b(bar);
1713
1714 std::this_thread::sleep_for(100ms);
1715
Josh Gaoe04ca272018-01-16 15:38:17 -08001716 raise_debugger_signal(dump_type);
1717 _exit(0);
1718 },
1719 &seccomp_fork);
1720
1721 StartIntercept(&output_fd, dump_type);
1722 FinishCrasher();
1723 AssertDeath(0);
1724 FinishIntercept(&intercept_result);
1725 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1726
1727 std::string result;
1728 ConsumeFd(std::move(output_fd), &result);
1729 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
Josh Gao6f9eeec2018-09-12 13:55:47 -07001730 ASSERT_BACKTRACE_FRAME(result, "foo");
1731 ASSERT_BACKTRACE_FRAME(result, "bar");
Josh Gaoe04ca272018-01-16 15:38:17 -08001732}
1733
Christopher Ferris7c2e7e32022-05-27 12:57:58 -07001734TEST_F(CrasherTest, seccomp_backtrace_from_thread) {
1735 int intercept_result;
1736 unique_fd output_fd;
1737
1738 static const auto dump_type = kDebuggerdNativeBacktrace;
1739 StartProcess(
1740 []() {
1741 std::thread a(foo);
1742 std::thread b(bar);
1743
1744 std::this_thread::sleep_for(100ms);
1745
1746 std::thread raise_thread([] {
1747 raise_debugger_signal(dump_type);
1748 _exit(0);
1749 });
1750 raise_thread.join();
1751 },
1752 &seccomp_fork);
1753
1754 StartIntercept(&output_fd, dump_type);
1755 FinishCrasher();
1756 AssertDeath(0);
1757 FinishIntercept(&intercept_result);
1758 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1759
1760 std::string result;
1761 ConsumeFd(std::move(output_fd), &result);
1762 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
1763 ASSERT_BACKTRACE_FRAME(result, "foo");
1764 ASSERT_BACKTRACE_FRAME(result, "bar");
1765 ASSERT_BACKTRACE_FRAME(result, "main");
1766}
1767
Josh Gaoe04ca272018-01-16 15:38:17 -08001768TEST_F(CrasherTest, seccomp_crash_logcat) {
1769 StartProcess([]() { abort(); }, &seccomp_fork);
1770 FinishCrasher();
1771
1772 // Make sure we don't get SIGSYS when trying to dump a crash to logcat.
1773 AssertDeath(SIGABRT);
1774}
1775
Josh Gaofd13bf02017-08-18 15:37:26 -07001776TEST_F(CrasherTest, competing_tracer) {
1777 int intercept_result;
1778 unique_fd output_fd;
1779 StartProcess([]() {
Josh Gao2b2ae0c2017-08-21 14:31:17 -07001780 raise(SIGABRT);
Josh Gaofd13bf02017-08-18 15:37:26 -07001781 });
1782
1783 StartIntercept(&output_fd);
Josh Gaofd13bf02017-08-18 15:37:26 -07001784
1785 ASSERT_EQ(0, ptrace(PTRACE_SEIZE, crasher_pid, 0, 0));
Josh Gao2b2ae0c2017-08-21 14:31:17 -07001786 FinishCrasher();
Josh Gaofd13bf02017-08-18 15:37:26 -07001787
1788 int status;
Christopher Ferris172b0a02019-09-18 17:48:30 -07001789 ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
Josh Gaofd13bf02017-08-18 15:37:26 -07001790 ASSERT_TRUE(WIFSTOPPED(status));
1791 ASSERT_EQ(SIGABRT, WSTOPSIG(status));
1792
1793 ASSERT_EQ(0, ptrace(PTRACE_CONT, crasher_pid, 0, SIGABRT));
1794 FinishIntercept(&intercept_result);
1795 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1796
1797 std::string result;
1798 ConsumeFd(std::move(output_fd), &result);
1799 std::string regex = R"(failed to attach to thread \d+, already traced by )";
1800 regex += std::to_string(gettid());
1801 regex += R"( \(.+debuggerd_test)";
1802 ASSERT_MATCH(result, regex.c_str());
1803
Christopher Ferris172b0a02019-09-18 17:48:30 -07001804 ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
Josh Gao2b2ae0c2017-08-21 14:31:17 -07001805 ASSERT_TRUE(WIFSTOPPED(status));
1806 ASSERT_EQ(SIGABRT, WSTOPSIG(status));
1807
Josh Gaofd13bf02017-08-18 15:37:26 -07001808 ASSERT_EQ(0, ptrace(PTRACE_DETACH, crasher_pid, 0, SIGABRT));
1809 AssertDeath(SIGABRT);
1810}
1811
Mitch Phillips18ce5422023-01-19 14:23:49 -08001812struct GwpAsanTestParameters {
1813 size_t alloc_size;
1814 bool free_before_access;
1815 int access_offset;
1816 std::string cause_needle; // Needle to be found in the "Cause: [GWP-ASan]" line.
1817};
1818
1819struct GwpAsanCrasherTest
1820 : CrasherTest,
1821 testing::WithParamInterface<
1822 std::tuple<GwpAsanTestParameters, /* recoverable */ bool, /* seccomp */ bool>> {};
1823
1824GwpAsanTestParameters gwp_asan_tests[] = {
1825 {/* alloc_size */ 7, /* free_before_access */ true, /* access_offset */ 0,
1826 "Use After Free, 0 bytes into a 7-byte allocation"},
1827 {/* alloc_size */ 15, /* free_before_access */ true, /* access_offset */ 1,
1828 "Use After Free, 1 byte into a 15-byte allocation"},
1829 {/* alloc_size */ 4096, /* free_before_access */ false, /* access_offset */ 4098,
1830 "Buffer Overflow, 2 bytes right of a 4096-byte allocation"},
1831 {/* alloc_size */ 4096, /* free_before_access */ false, /* access_offset */ -1,
1832 "Buffer Underflow, 1 byte left of a 4096-byte allocation"},
1833};
1834
1835INSTANTIATE_TEST_SUITE_P(
1836 GwpAsanTests, GwpAsanCrasherTest,
1837 testing::Combine(testing::ValuesIn(gwp_asan_tests),
1838 /* recoverable */ testing::Bool(),
1839 /* seccomp */ testing::Bool()),
1840 [](const testing::TestParamInfo<
1841 std::tuple<GwpAsanTestParameters, /* recoverable */ bool, /* seccomp */ bool>>& info) {
1842 const GwpAsanTestParameters& params = std::get<0>(info.param);
1843 std::string name = params.free_before_access ? "UseAfterFree" : "Overflow";
1844 name += testing::PrintToString(params.alloc_size);
1845 name += "Alloc";
1846 if (params.access_offset < 0) {
1847 name += "Left";
1848 name += testing::PrintToString(params.access_offset * -1);
1849 } else {
1850 name += "Right";
1851 name += testing::PrintToString(params.access_offset);
1852 }
1853 name += "Bytes";
1854 if (std::get<1>(info.param)) name += "Recoverable";
1855 if (std::get<2>(info.param)) name += "Seccomp";
1856 return name;
1857 });
1858
1859TEST_P(GwpAsanCrasherTest, run_gwp_asan_test) {
1860 if (mte_supported()) {
1861 // Skip this test on MTE hardware, as MTE will reliably catch these errors
1862 // instead of GWP-ASan.
1863 GTEST_SKIP() << "Skipped on MTE.";
1864 }
1865 // Skip this test on HWASan, which will reliably catch test errors as well.
1866 SKIP_WITH_HWASAN;
1867
1868 GwpAsanTestParameters params = std::get<0>(GetParam());
1869 bool recoverable = std::get<1>(GetParam());
1870 LogcatCollector logcat_collector;
1871
1872 int intercept_result;
1873 unique_fd output_fd;
1874 StartProcess([&recoverable]() {
1875 const char* env[] = {"GWP_ASAN_SAMPLE_RATE=1", "GWP_ASAN_PROCESS_SAMPLING=1",
1876 "GWP_ASAN_MAX_ALLOCS=40000", nullptr, nullptr};
Mitch Phillipsa2f53352024-04-09 15:59:12 +02001877 if (!recoverable) {
1878 env[3] = "GWP_ASAN_RECOVERABLE=false";
Mitch Phillips18ce5422023-01-19 14:23:49 -08001879 }
1880 std::string test_name = ::testing::UnitTest::GetInstance()->current_test_info()->name();
1881 test_name = std::regex_replace(test_name, std::regex("run_gwp_asan_test"),
1882 "DISABLED_run_gwp_asan_test");
1883 std::string test_filter = "--gtest_filter=*";
1884 test_filter += test_name;
1885 std::string this_binary = android::base::GetExecutablePath();
1886 const char* args[] = {this_binary.c_str(), "--gtest_also_run_disabled_tests",
1887 test_filter.c_str(), nullptr};
1888 // We check the crash report from a debuggerd handler and from logcat. The
1889 // echo from stdout/stderr of the subprocess trips up atest, because it
1890 // doesn't like that two tests started in a row without the first one
1891 // finishing (even though the second one is in a subprocess).
1892 close(STDOUT_FILENO);
1893 close(STDERR_FILENO);
1894 execve(this_binary.c_str(), const_cast<char**>(args), const_cast<char**>(env));
1895 });
1896
1897 StartIntercept(&output_fd);
1898 FinishCrasher();
1899 if (recoverable) {
1900 AssertDeath(0);
1901 } else {
1902 AssertDeath(SIGSEGV);
1903 }
1904 FinishIntercept(&intercept_result);
1905
1906 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1907
1908 std::vector<std::string> log_sources(2);
1909 ConsumeFd(std::move(output_fd), &log_sources[0]);
1910 logcat_collector.Collect(&log_sources[1]);
1911
1912 // seccomp forces the fallback handler, which doesn't print GWP-ASan debugging
1913 // information. Make sure the recovery still works, but the report won't be
1914 // hugely useful, it looks like a regular SEGV.
1915 bool seccomp = std::get<2>(GetParam());
1916 if (!seccomp) {
1917 for (const auto& result : log_sources) {
1918 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\))");
1919 ASSERT_MATCH(result, R"(Cause: \[GWP-ASan\]: )" + params.cause_needle);
1920 if (params.free_before_access) {
1921 ASSERT_MATCH(result, R"(deallocated by thread .*\n.*#00 pc)");
1922 }
1923 ASSERT_MATCH(result, R"((^|\s)allocated by thread .*\n.*#00 pc)");
1924 }
1925 }
1926}
1927
1928TEST_P(GwpAsanCrasherTest, DISABLED_run_gwp_asan_test) {
1929 GwpAsanTestParameters params = std::get<0>(GetParam());
1930 bool seccomp = std::get<2>(GetParam());
1931 if (seccomp) {
1932 ScopedMinijail jail{minijail_new()};
1933 setup_jail(jail.get());
1934 minijail_enter(jail.get());
1935 }
1936
1937 // Use 'volatile' to prevent a very clever compiler eliminating the store.
1938 char* volatile p = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1939 if (params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
1940 p[params.access_offset] = 42;
1941 if (!params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
Mitch Phillips70aa2192023-02-22 11:31:36 -08001942
1943 bool recoverable = std::get<1>(GetParam());
1944 ASSERT_TRUE(recoverable); // Non-recoverable should have crashed.
1945
1946 // As we're in recoverable mode, trigger another 2x use-after-frees (ensuring
1947 // we end with at least one in a different slot), make sure the process still
1948 // doesn't crash.
1949 p = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1950 char* volatile p2 = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1951 free(static_cast<void*>(const_cast<char*>(p)));
1952 free(static_cast<void*>(const_cast<char*>(p2)));
1953 *p = 42;
1954 *p2 = 42;
1955
1956 // Under clang coverage (which is a default TEST_MAPPING presubmit target), the
1957 // recoverable+seccomp tests fail because the minijail prevents some atexit syscalls that clang
1958 // coverage does. Thus, skip the atexit handlers.
1959 _exit(0);
Mitch Phillips18ce5422023-01-19 14:23:49 -08001960}
1961
Josh Gaobf06a402018-08-27 16:34:01 -07001962TEST_F(CrasherTest, fdsan_warning_abort_message) {
1963 int intercept_result;
1964 unique_fd output_fd;
1965
1966 StartProcess([]() {
1967 android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
Christopher Ferris172b0a02019-09-18 17:48:30 -07001968 unique_fd fd(TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY | O_CLOEXEC)));
Josh Gaobf06a402018-08-27 16:34:01 -07001969 if (fd == -1) {
1970 abort();
1971 }
1972 close(fd.get());
1973 _exit(0);
1974 });
1975
1976 StartIntercept(&output_fd);
1977 FinishCrasher();
1978 AssertDeath(0);
1979 FinishIntercept(&intercept_result);
1980 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1981
1982 std::string result;
1983 ConsumeFd(std::move(output_fd), &result);
1984 ASSERT_MATCH(result, "Abort message: 'attempted to close");
1985}
1986
Josh Gaoc3c8c022017-02-13 16:36:18 -08001987TEST(crash_dump, zombie) {
1988 pid_t forkpid = fork();
1989
Josh Gaoc3c8c022017-02-13 16:36:18 -08001990 pid_t rc;
1991 int status;
1992
1993 if (forkpid == 0) {
1994 errno = 0;
1995 rc = waitpid(-1, &status, WNOHANG | __WALL | __WNOTHREAD);
1996 if (rc != -1 || errno != ECHILD) {
1997 errx(2, "first waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
1998 }
1999
Josh Gaoa48b41b2019-12-13 14:11:04 -08002000 raise(BIONIC_SIGNAL_DEBUGGER);
Josh Gaoc3c8c022017-02-13 16:36:18 -08002001
2002 errno = 0;
Christopher Ferris172b0a02019-09-18 17:48:30 -07002003 rc = TEMP_FAILURE_RETRY(waitpid(-1, &status, __WALL | __WNOTHREAD));
Josh Gaoc3c8c022017-02-13 16:36:18 -08002004 if (rc != -1 || errno != ECHILD) {
2005 errx(2, "second waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
2006 }
2007 _exit(0);
2008 } else {
Christopher Ferris172b0a02019-09-18 17:48:30 -07002009 rc = TEMP_FAILURE_RETRY(waitpid(forkpid, &status, 0));
Josh Gaoc3c8c022017-02-13 16:36:18 -08002010 ASSERT_EQ(forkpid, rc);
2011 ASSERT_TRUE(WIFEXITED(status));
2012 ASSERT_EQ(0, WEXITSTATUS(status));
2013 }
2014}
Josh Gao352a8452017-03-30 16:46:21 -07002015
2016TEST(tombstoned, no_notify) {
2017 // Do this a few times.
2018 for (int i = 0; i < 3; ++i) {
2019 pid_t pid = 123'456'789 + i;
2020
2021 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002022 InterceptResponse response = {};
2023 tombstoned_intercept(pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2024 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2025 << "Error message: " << response.error_message;
Josh Gao352a8452017-03-30 16:46:21 -07002026
2027 {
2028 unique_fd tombstoned_socket, input_fd;
Narayan Kamatha73df602017-05-24 15:07:25 +01002029 ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
Josh Gao352a8452017-03-30 16:46:21 -07002030 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid)));
2031 }
2032
2033 pid_t read_pid;
2034 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid)));
2035 ASSERT_EQ(read_pid, pid);
2036 }
2037}
2038
2039TEST(tombstoned, stress) {
2040 // Spawn threads to simultaneously do a bunch of failing dumps and a bunch of successful dumps.
2041 static constexpr int kDumpCount = 100;
2042
2043 std::atomic<bool> start(false);
2044 std::vector<std::thread> threads;
2045 threads.emplace_back([&start]() {
2046 while (!start) {
2047 continue;
2048 }
2049
2050 // Use a way out of range pid, to avoid stomping on an actual process.
2051 pid_t pid_base = 1'000'000;
2052
2053 for (int dump = 0; dump < kDumpCount; ++dump) {
2054 pid_t pid = pid_base + dump;
2055
2056 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002057 InterceptResponse response = {};
2058 tombstoned_intercept(pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2059 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2060 << "Error messeage: " << response.error_message;
Josh Gao352a8452017-03-30 16:46:21 -07002061
2062 // Pretend to crash, and then immediately close the socket.
2063 unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName,
2064 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
2065 if (sockfd == -1) {
2066 FAIL() << "failed to connect to tombstoned: " << strerror(errno);
2067 }
2068 TombstonedCrashPacket packet = {};
2069 packet.packet_type = CrashPacketType::kDumpRequest;
2070 packet.packet.dump_request.pid = pid;
2071 if (TEMP_FAILURE_RETRY(write(sockfd, &packet, sizeof(packet))) != sizeof(packet)) {
2072 FAIL() << "failed to write to tombstoned: " << strerror(errno);
2073 }
2074
2075 continue;
2076 }
2077 });
2078
2079 threads.emplace_back([&start]() {
2080 while (!start) {
2081 continue;
2082 }
2083
2084 // Use a way out of range pid, to avoid stomping on an actual process.
2085 pid_t pid_base = 2'000'000;
2086
2087 for (int dump = 0; dump < kDumpCount; ++dump) {
2088 pid_t pid = pid_base + dump;
2089
2090 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002091 InterceptResponse response = {};
2092 tombstoned_intercept(pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2093 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2094 << "Error message: " << response.error_message;
Josh Gao352a8452017-03-30 16:46:21 -07002095
2096 {
2097 unique_fd tombstoned_socket, input_fd;
Narayan Kamatha73df602017-05-24 15:07:25 +01002098 ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
Josh Gao352a8452017-03-30 16:46:21 -07002099 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid)));
2100 tombstoned_notify_completion(tombstoned_socket.get());
2101 }
2102
2103 // TODO: Fix the race that requires this sleep.
2104 std::this_thread::sleep_for(50ms);
2105
2106 pid_t read_pid;
2107 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid)));
2108 ASSERT_EQ(read_pid, pid);
2109 }
2110 });
2111
2112 start = true;
2113
2114 for (std::thread& thread : threads) {
2115 thread.join();
2116 }
2117}
Narayan Kamathca5e9082017-06-02 15:42:06 +01002118
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002119TEST(tombstoned, intercept_java_trace_smoke) {
Narayan Kamathca5e9082017-06-02 15:42:06 +01002120 // Using a "real" PID is a little dangerous here - if the test fails
2121 // or crashes, we might end up getting a bogus / unreliable stack
2122 // trace.
2123 const pid_t self = getpid();
2124
2125 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002126 InterceptResponse response = {};
2127 tombstoned_intercept(self, &intercept_fd, &output_fd, &response, kDebuggerdJavaBacktrace);
2128 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2129 << "Error message: " << response.error_message;
Narayan Kamathca5e9082017-06-02 15:42:06 +01002130
Josh Gao76e1e302021-01-26 15:53:11 -08002131 // First connect to tombstoned requesting a native tombstone. This
Narayan Kamathca5e9082017-06-02 15:42:06 +01002132 // should result in a "regular" FD and not the installed intercept.
2133 const char native[] = "native";
2134 unique_fd tombstoned_socket, input_fd;
Josh Gao76e1e302021-01-26 15:53:11 -08002135 ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
Narayan Kamathca5e9082017-06-02 15:42:06 +01002136 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), native, sizeof(native)));
2137 tombstoned_notify_completion(tombstoned_socket.get());
2138
2139 // Then, connect to tombstoned asking for a java backtrace. This *should*
2140 // trigger the intercept.
2141 const char java[] = "java";
2142 ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdJavaBacktrace));
2143 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), java, sizeof(java)));
2144 tombstoned_notify_completion(tombstoned_socket.get());
2145
2146 char outbuf[sizeof(java)];
2147 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
2148 ASSERT_STREQ("java", outbuf);
2149}
2150
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002151TEST(tombstoned, intercept_multiple_dump_types) {
Narayan Kamathca5e9082017-06-02 15:42:06 +01002152 const pid_t fake_pid = 1'234'567;
2153 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002154 InterceptResponse response = {};
2155 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdJavaBacktrace);
2156 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2157 << "Error message: " << response.error_message;
Narayan Kamathca5e9082017-06-02 15:42:06 +01002158
2159 unique_fd intercept_fd_2, output_fd_2;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002160 tombstoned_intercept(fake_pid, &intercept_fd_2, &output_fd_2, &response,
2161 kDebuggerdNativeBacktrace);
2162 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2163 << "Error message: " << response.error_message;
2164}
2165
2166TEST(tombstoned, intercept_bad_pid) {
2167 const pid_t fake_pid = -1;
2168 unique_fd intercept_fd, output_fd;
2169 InterceptResponse response = {};
2170 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdNativeBacktrace);
2171 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2172 << "Error message: " << response.error_message;
2173 ASSERT_MATCH(response.error_message, "bad pid");
2174}
2175
2176TEST(tombstoned, intercept_bad_dump_types) {
2177 const pid_t fake_pid = 1'234'567;
2178 unique_fd intercept_fd, output_fd;
2179 InterceptResponse response = {};
2180 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response,
2181 static_cast<DebuggerdDumpType>(20));
2182 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2183 << "Error message: " << response.error_message;
2184 ASSERT_MATCH(response.error_message, "bad dump type \\[unknown\\]");
2185
2186 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdAnyIntercept);
2187 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2188 << "Error message: " << response.error_message;
2189 ASSERT_MATCH(response.error_message, "bad dump type kDebuggerdAnyIntercept");
2190
2191 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstoneProto);
2192 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2193 << "Error message: " << response.error_message;
2194 ASSERT_MATCH(response.error_message, "bad dump type kDebuggerdTombstoneProto");
2195}
2196
2197TEST(tombstoned, intercept_already_registered) {
2198 const pid_t fake_pid = 1'234'567;
2199 unique_fd intercept_fd1, output_fd1;
2200 InterceptResponse response = {};
2201 tombstoned_intercept(fake_pid, &intercept_fd1, &output_fd1, &response, kDebuggerdTombstone);
2202 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2203 << "Error message: " << response.error_message;
2204
2205 unique_fd intercept_fd2, output_fd2;
2206 tombstoned_intercept(fake_pid, &intercept_fd2, &output_fd2, &response, kDebuggerdTombstone);
2207 ASSERT_EQ(InterceptStatus::kFailedAlreadyRegistered, response.status)
2208 << "Error message: " << response.error_message;
2209 ASSERT_MATCH(response.error_message, "already registered, type kDebuggerdTombstone");
2210}
2211
2212TEST(tombstoned, intercept_tombstone_proto_matched_to_tombstone) {
2213 const pid_t fake_pid = 1'234'567;
2214
2215 unique_fd intercept_fd, output_fd;
2216 InterceptResponse response = {};
2217 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2218 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2219 << "Error message: " << response.error_message;
2220
2221 const char data[] = "tombstone_proto";
2222 unique_fd tombstoned_socket, input_fd;
2223 ASSERT_TRUE(
2224 tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdTombstoneProto));
2225 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), data, sizeof(data)));
2226 tombstoned_notify_completion(tombstoned_socket.get());
2227
2228 char outbuf[sizeof(data)];
2229 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
2230 ASSERT_STREQ("tombstone_proto", outbuf);
Narayan Kamathca5e9082017-06-02 15:42:06 +01002231}
2232
2233TEST(tombstoned, intercept_any) {
2234 const pid_t fake_pid = 1'234'567;
2235
2236 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002237 InterceptResponse response = {};
2238 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdNativeBacktrace);
2239 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2240 << "Error message: " << response.error_message;
Narayan Kamathca5e9082017-06-02 15:42:06 +01002241
2242 const char any[] = "any";
2243 unique_fd tombstoned_socket, input_fd;
2244 ASSERT_TRUE(tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdAnyIntercept));
2245 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), any, sizeof(any)));
2246 tombstoned_notify_completion(tombstoned_socket.get());
2247
2248 char outbuf[sizeof(any)];
2249 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
2250 ASSERT_STREQ("any", outbuf);
2251}
Josh Gao2b22ae12018-09-12 14:51:03 -07002252
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002253TEST(tombstoned, intercept_any_failed_with_multiple_intercepts) {
2254 const pid_t fake_pid = 1'234'567;
2255
2256 InterceptResponse response = {};
2257 unique_fd intercept_fd1, output_fd1;
2258 tombstoned_intercept(fake_pid, &intercept_fd1, &output_fd1, &response, kDebuggerdNativeBacktrace);
2259 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2260 << "Error message: " << response.error_message;
2261
2262 unique_fd intercept_fd2, output_fd2;
2263 tombstoned_intercept(fake_pid, &intercept_fd2, &output_fd2, &response, kDebuggerdJavaBacktrace);
2264 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2265 << "Error message: " << response.error_message;
2266
2267 unique_fd tombstoned_socket, input_fd;
2268 ASSERT_FALSE(tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdAnyIntercept));
2269}
2270
2271TEST(tombstoned, intercept_multiple_verify_intercept) {
2272 // Need to use our pid for java since that will verify the pid.
2273 const pid_t fake_pid = getpid();
2274
2275 InterceptResponse response = {};
2276 unique_fd intercept_fd1, output_fd1;
2277 tombstoned_intercept(fake_pid, &intercept_fd1, &output_fd1, &response, kDebuggerdNativeBacktrace);
2278 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2279 << "Error message: " << response.error_message;
2280
2281 unique_fd intercept_fd2, output_fd2;
2282 tombstoned_intercept(fake_pid, &intercept_fd2, &output_fd2, &response, kDebuggerdJavaBacktrace);
2283 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2284 << "Error message: " << response.error_message;
2285
2286 unique_fd intercept_fd3, output_fd3;
2287 tombstoned_intercept(fake_pid, &intercept_fd3, &output_fd3, &response, kDebuggerdTombstone);
2288 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2289 << "Error message: " << response.error_message;
2290
2291 const char native_data[] = "native";
2292 unique_fd tombstoned_socket1, input_fd1;
2293 ASSERT_TRUE(
2294 tombstoned_connect(fake_pid, &tombstoned_socket1, &input_fd1, kDebuggerdNativeBacktrace));
2295 ASSERT_TRUE(android::base::WriteFully(input_fd1.get(), native_data, sizeof(native_data)));
2296 tombstoned_notify_completion(tombstoned_socket1.get());
2297
2298 char native_outbuf[sizeof(native_data)];
2299 ASSERT_TRUE(android::base::ReadFully(output_fd1.get(), native_outbuf, sizeof(native_outbuf)));
2300 ASSERT_STREQ("native", native_outbuf);
2301
2302 const char java_data[] = "java";
2303 unique_fd tombstoned_socket2, input_fd2;
2304 ASSERT_TRUE(
2305 tombstoned_connect(fake_pid, &tombstoned_socket2, &input_fd2, kDebuggerdJavaBacktrace));
2306 ASSERT_TRUE(android::base::WriteFully(input_fd2.get(), java_data, sizeof(java_data)));
2307 tombstoned_notify_completion(tombstoned_socket2.get());
2308
2309 char java_outbuf[sizeof(java_data)];
2310 ASSERT_TRUE(android::base::ReadFully(output_fd2.get(), java_outbuf, sizeof(java_outbuf)));
2311 ASSERT_STREQ("java", java_outbuf);
2312
2313 const char tomb_data[] = "tombstone";
2314 unique_fd tombstoned_socket3, input_fd3;
2315 ASSERT_TRUE(tombstoned_connect(fake_pid, &tombstoned_socket3, &input_fd3, kDebuggerdTombstone));
2316 ASSERT_TRUE(android::base::WriteFully(input_fd3.get(), tomb_data, sizeof(tomb_data)));
2317 tombstoned_notify_completion(tombstoned_socket3.get());
2318
2319 char tomb_outbuf[sizeof(tomb_data)];
2320 ASSERT_TRUE(android::base::ReadFully(output_fd3.get(), tomb_outbuf, sizeof(tomb_outbuf)));
2321 ASSERT_STREQ("tombstone", tomb_outbuf);
2322}
2323
Josh Gao2b22ae12018-09-12 14:51:03 -07002324TEST(tombstoned, interceptless_backtrace) {
2325 // Generate 50 backtraces, and then check to see that we haven't created 50 new tombstones.
2326 auto get_tombstone_timestamps = []() -> std::map<int, time_t> {
2327 std::map<int, time_t> result;
2328 for (int i = 0; i < 99; ++i) {
2329 std::string path = android::base::StringPrintf("/data/tombstones/tombstone_%02d", i);
2330 struct stat st;
2331 if (stat(path.c_str(), &st) == 0) {
2332 result[i] = st.st_mtim.tv_sec;
2333 }
2334 }
2335 return result;
2336 };
2337
2338 auto before = get_tombstone_timestamps();
2339 for (int i = 0; i < 50; ++i) {
2340 raise_debugger_signal(kDebuggerdNativeBacktrace);
2341 }
2342 auto after = get_tombstone_timestamps();
2343
2344 int diff = 0;
2345 for (int i = 0; i < 99; ++i) {
2346 if (after.count(i) == 0) {
2347 continue;
2348 }
2349 if (before.count(i) == 0) {
2350 ++diff;
2351 continue;
2352 }
2353 if (before[i] != after[i]) {
2354 ++diff;
2355 }
2356 }
2357
2358 // We can't be sure that nothing's crash looping in the background.
2359 // This should be good enough, though...
2360 ASSERT_LT(diff, 10) << "too many new tombstones; is something crashing in the background?";
2361}
Christopher Ferris481e8372019-07-15 17:13:24 -07002362
2363static __attribute__((__noinline__)) void overflow_stack(void* p) {
2364 void* buf[1];
2365 buf[0] = p;
2366 static volatile void* global = buf;
2367 if (global) {
2368 global = buf;
2369 overflow_stack(&buf);
2370 }
2371}
2372
2373TEST_F(CrasherTest, stack_overflow) {
2374 int intercept_result;
2375 unique_fd output_fd;
2376 StartProcess([]() { overflow_stack(nullptr); });
2377
2378 StartIntercept(&output_fd);
2379 FinishCrasher();
2380 AssertDeath(SIGSEGV);
2381 FinishIntercept(&intercept_result);
2382
2383 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2384
2385 std::string result;
2386 ConsumeFd(std::move(output_fd), &result);
2387 ASSERT_MATCH(result, R"(Cause: stack pointer[^\n]*stack overflow.\n)");
2388}
Josh Gao76e1e302021-01-26 15:53:11 -08002389
Christopher Ferris22035cc2023-01-31 17:50:22 -08002390static std::string GetTestLibraryPath() {
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002391 std::string test_lib(testing::internal::GetArgvs()[0]);
2392 auto const value = test_lib.find_last_of('/');
2393 if (value == std::string::npos) {
2394 test_lib = "./";
2395 } else {
2396 test_lib = test_lib.substr(0, value + 1) + "./";
2397 }
Christopher Ferris22035cc2023-01-31 17:50:22 -08002398 return test_lib + "libcrash_test.so";
2399}
2400
2401static void CreateEmbeddedLibrary(int out_fd) {
2402 std::string test_lib(GetTestLibraryPath());
2403 android::base::unique_fd fd(open(test_lib.c_str(), O_RDONLY | O_CLOEXEC));
2404 ASSERT_NE(fd.get(), -1);
2405 off_t file_size = lseek(fd, 0, SEEK_END);
2406 ASSERT_EQ(lseek(fd, 0, SEEK_SET), 0);
2407 std::vector<uint8_t> contents(file_size);
2408 ASSERT_TRUE(android::base::ReadFully(fd, contents.data(), contents.size()));
2409
2410 // Put the shared library data at a pagesize() offset.
2411 ASSERT_EQ(lseek(out_fd, 4 * getpagesize(), SEEK_CUR), 4 * getpagesize());
2412 ASSERT_EQ(static_cast<size_t>(write(out_fd, contents.data(), contents.size())), contents.size());
2413}
2414
2415TEST_F(CrasherTest, non_zero_offset_in_library) {
2416 int intercept_result;
2417 unique_fd output_fd;
2418 TemporaryFile tf;
2419 CreateEmbeddedLibrary(tf.fd);
2420 StartProcess([&tf]() {
2421 android_dlextinfo extinfo{};
2422 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
2423 extinfo.library_fd = tf.fd;
2424 extinfo.library_fd_offset = 4 * getpagesize();
2425 void* handle = android_dlopen_ext(tf.path, RTLD_NOW, &extinfo);
2426 if (handle == nullptr) {
2427 _exit(1);
2428 }
2429 void (*crash_func)() = reinterpret_cast<void (*)()>(dlsym(handle, "crash"));
2430 if (crash_func == nullptr) {
2431 _exit(1);
2432 }
2433 crash_func();
2434 });
2435
2436 StartIntercept(&output_fd);
2437 FinishCrasher();
2438 AssertDeath(SIGSEGV);
2439 FinishIntercept(&intercept_result);
2440
2441 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2442
2443 std::string result;
2444 ConsumeFd(std::move(output_fd), &result);
2445
2446 // Verify the crash includes an offset value in the backtrace.
2447 std::string match_str = android::base::StringPrintf("%s\\!libcrash_test.so \\(offset 0x%x\\)",
2448 tf.path, 4 * getpagesize());
2449 ASSERT_MATCH(result, match_str);
2450}
2451
2452static bool CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) {
2453 std::string test_lib(GetTestLibraryPath());
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002454
2455 *tmp_so_name = std::string(tmp_dir) + "/libcrash_test.so";
2456 std::string cp_cmd = android::base::StringPrintf("cp %s %s", test_lib.c_str(), tmp_dir);
2457
2458 // Copy the shared so to a tempory directory.
2459 return system(cp_cmd.c_str()) == 0;
2460}
2461
2462TEST_F(CrasherTest, unreadable_elf) {
2463 int intercept_result;
2464 unique_fd output_fd;
Christopher Ferrisc95047d2022-03-14 15:02:11 -07002465 std::string tmp_so_name;
2466 StartProcess([&tmp_so_name]() {
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002467 TemporaryDir td;
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002468 if (!CopySharedLibrary(td.path, &tmp_so_name)) {
2469 _exit(1);
2470 }
2471 void* handle = dlopen(tmp_so_name.c_str(), RTLD_NOW);
2472 if (handle == nullptr) {
2473 _exit(1);
2474 }
2475 // Delete the original shared library so that we get the warning
2476 // about unreadable elf files.
2477 if (unlink(tmp_so_name.c_str()) == -1) {
2478 _exit(1);
2479 }
2480 void (*crash_func)() = reinterpret_cast<void (*)()>(dlsym(handle, "crash"));
2481 if (crash_func == nullptr) {
2482 _exit(1);
2483 }
2484 crash_func();
2485 });
2486
2487 StartIntercept(&output_fd);
2488 FinishCrasher();
2489 AssertDeath(SIGSEGV);
2490 FinishIntercept(&intercept_result);
2491
2492 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2493
2494 std::string result;
2495 ConsumeFd(std::move(output_fd), &result);
2496 ASSERT_MATCH(result, R"(NOTE: Function names and BuildId information is missing )");
Christopher Ferrisc95047d2022-03-14 15:02:11 -07002497 std::string match_str = "NOTE: " + tmp_so_name;
2498 ASSERT_MATCH(result, match_str);
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002499}
2500
Christopher Ferris20f50ec2024-01-03 02:30:03 +00002501void CheckForTombstone(const struct stat& text_st, std::optional<std::string>& tombstone_file) {
2502 static std::regex tombstone_re("tombstone_\\d+");
Christopher Ferris35da2882021-02-17 15:39:06 -08002503 std::unique_ptr<DIR, decltype(&closedir)> dir_h(opendir("/data/tombstones"), closedir);
2504 ASSERT_TRUE(dir_h != nullptr);
Christopher Ferris35da2882021-02-17 15:39:06 -08002505 dirent* entry;
2506 while ((entry = readdir(dir_h.get())) != nullptr) {
2507 if (!std::regex_match(entry->d_name, tombstone_re)) {
2508 continue;
2509 }
2510 std::string path = android::base::StringPrintf("/data/tombstones/%s", entry->d_name);
Josh Gao76e1e302021-01-26 15:53:11 -08002511
2512 struct stat st;
2513 if (TEMP_FAILURE_RETRY(stat(path.c_str(), &st)) != 0) {
2514 continue;
2515 }
2516
2517 if (st.st_dev == text_st.st_dev && st.st_ino == text_st.st_ino) {
Christopher Ferris35da2882021-02-17 15:39:06 -08002518 tombstone_file = path;
Josh Gao76e1e302021-01-26 15:53:11 -08002519 break;
2520 }
2521 }
Christopher Ferris20f50ec2024-01-03 02:30:03 +00002522}
Josh Gao76e1e302021-01-26 15:53:11 -08002523
Christopher Ferris20f50ec2024-01-03 02:30:03 +00002524TEST(tombstoned, proto) {
2525 const pid_t self = getpid();
2526 unique_fd tombstoned_socket, text_fd, proto_fd;
2527 ASSERT_TRUE(
2528 tombstoned_connect(self, &tombstoned_socket, &text_fd, &proto_fd, kDebuggerdTombstoneProto));
2529
2530 tombstoned_notify_completion(tombstoned_socket.get());
2531
2532 ASSERT_NE(-1, text_fd.get());
2533 ASSERT_NE(-1, proto_fd.get());
2534
2535 struct stat text_st;
2536 ASSERT_EQ(0, fstat(text_fd.get(), &text_st));
2537
2538 std::optional<std::string> tombstone_file;
2539 // Allow up to 5 seconds for the tombstone to be written to the system.
2540 const auto max_wait_time = std::chrono::seconds(5) * android::base::HwTimeoutMultiplier();
2541 const auto start = std::chrono::high_resolution_clock::now();
2542 while (true) {
2543 std::this_thread::sleep_for(100ms);
2544 CheckForTombstone(text_st, tombstone_file);
2545 if (tombstone_file) {
2546 break;
2547 }
2548 if (std::chrono::high_resolution_clock::now() - start > max_wait_time) {
2549 break;
2550 }
2551 }
2552
2553 ASSERT_TRUE(tombstone_file) << "Timed out trying to find tombstone file.";
Christopher Ferris35da2882021-02-17 15:39:06 -08002554 std::string proto_path = tombstone_file.value() + ".pb";
Josh Gao76e1e302021-01-26 15:53:11 -08002555
2556 struct stat proto_fd_st;
2557 struct stat proto_file_st;
2558 ASSERT_EQ(0, fstat(proto_fd.get(), &proto_fd_st));
2559 ASSERT_EQ(0, stat(proto_path.c_str(), &proto_file_st));
2560
2561 ASSERT_EQ(proto_fd_st.st_dev, proto_file_st.st_dev);
2562 ASSERT_EQ(proto_fd_st.st_ino, proto_file_st.st_ino);
2563}
2564
2565TEST(tombstoned, proto_intercept) {
2566 const pid_t self = getpid();
2567 unique_fd intercept_fd, output_fd;
Josh Gao76e1e302021-01-26 15:53:11 -08002568
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002569 InterceptResponse response = {};
2570 tombstoned_intercept(self, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2571 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2572 << "Error message: " << response.error_message;
Josh Gao76e1e302021-01-26 15:53:11 -08002573
2574 unique_fd tombstoned_socket, text_fd, proto_fd;
2575 ASSERT_TRUE(
2576 tombstoned_connect(self, &tombstoned_socket, &text_fd, &proto_fd, kDebuggerdTombstoneProto));
2577 ASSERT_TRUE(android::base::WriteStringToFd("foo", text_fd.get()));
2578 tombstoned_notify_completion(tombstoned_socket.get());
2579
2580 text_fd.reset();
2581
2582 std::string output;
2583 ASSERT_TRUE(android::base::ReadFdToString(output_fd, &output));
2584 ASSERT_EQ("foo", output);
2585}
Christopher Ferrisa3e9a0b2021-07-29 12:38:07 -07002586
2587// Verify that when an intercept is present for the main thread, and the signal
2588// is received on a different thread, the intercept still works.
2589TEST_F(CrasherTest, intercept_for_main_thread_signal_on_side_thread) {
2590 StartProcess([]() {
2591 std::thread thread([]() {
2592 // Raise the signal on the side thread.
2593 raise_debugger_signal(kDebuggerdNativeBacktrace);
2594 });
2595 thread.join();
2596 _exit(0);
2597 });
2598
2599 unique_fd output_fd;
2600 StartIntercept(&output_fd, kDebuggerdNativeBacktrace);
2601 FinishCrasher();
2602 AssertDeath(0);
2603
2604 int intercept_result;
2605 FinishIntercept(&intercept_result);
2606 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2607
2608 std::string result;
2609 ConsumeFd(std::move(output_fd), &result);
2610 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
2611}
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002612
2613static std::string format_pointer(uintptr_t ptr) {
2614#if defined(__LP64__)
2615 return android::base::StringPrintf("%08x'%08x", static_cast<uint32_t>(ptr >> 32),
2616 static_cast<uint32_t>(ptr & 0xffffffff));
2617#else
2618 return android::base::StringPrintf("%08x", static_cast<uint32_t>(ptr & 0xffffffff));
2619#endif
2620}
2621
2622static std::string format_pointer(void* ptr) {
2623 return format_pointer(reinterpret_cast<uintptr_t>(ptr));
2624}
2625
2626static std::string format_full_pointer(uintptr_t ptr) {
2627#if defined(__LP64__)
2628 return android::base::StringPrintf("%016" PRIx64, ptr);
2629#else
2630 return android::base::StringPrintf("%08x", ptr);
2631#endif
2632}
2633
2634static std::string format_full_pointer(void* ptr) {
2635 return format_full_pointer(reinterpret_cast<uintptr_t>(ptr));
2636}
2637
2638__attribute__((__noinline__)) int crash_call(uintptr_t ptr) {
2639 int* crash_ptr = reinterpret_cast<int*>(ptr);
2640 *crash_ptr = 1;
2641 return *crash_ptr;
2642}
2643
2644// Verify that a fault address before the first map is properly handled.
2645TEST_F(CrasherTest, fault_address_before_first_map) {
2646 StartProcess([]() {
2647 ASSERT_EQ(0, crash_call(0x1024));
2648 _exit(0);
2649 });
2650
2651 unique_fd output_fd;
2652 StartIntercept(&output_fd);
2653 FinishCrasher();
2654 AssertDeath(SIGSEGV);
2655
2656 int intercept_result;
2657 FinishIntercept(&intercept_result);
2658 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2659
2660 std::string result;
2661 ConsumeFd(std::move(output_fd), &result);
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002662 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+1024)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002663
2664 ASSERT_MATCH(result, R"(\nmemory map \(.*\):\n)");
2665
2666 std::string match_str = android::base::StringPrintf(
2667 R"(memory map .*:\n--->Fault address falls at %s before any mapped regions\n )",
2668 format_pointer(0x1024).c_str());
2669 ASSERT_MATCH(result, match_str);
2670}
2671
2672// Verify that a fault address after the last map is properly handled.
2673TEST_F(CrasherTest, fault_address_after_last_map) {
Florian Mayerb4979292022-04-15 14:35:17 -07002674 // This makes assumptions about the memory layout that are not true in HWASan
2675 // processes.
2676 SKIP_WITH_HWASAN;
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002677 uintptr_t crash_uptr = untag_address(UINTPTR_MAX - 15);
2678 StartProcess([crash_uptr]() {
2679 ASSERT_EQ(0, crash_call(crash_uptr));
2680 _exit(0);
2681 });
2682
2683 unique_fd output_fd;
2684 StartIntercept(&output_fd);
2685 FinishCrasher();
2686 AssertDeath(SIGSEGV);
2687
2688 int intercept_result;
2689 FinishIntercept(&intercept_result);
2690 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2691
2692 std::string result;
2693 ConsumeFd(std::move(output_fd), &result);
2694
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002695 std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x)";
2696 match_str += format_full_pointer(crash_uptr);
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002697 ASSERT_MATCH(result, match_str);
2698
Ryan Prichardbc227032024-02-29 14:40:57 -08002699 ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002700
Christopher Ferris3a0833c2023-07-28 13:07:53 -07002701 // Verifies that the fault address error message is at the end of the
2702 // maps section. To do this, the check below looks for the start of the
2703 // open files section or the start of the log file section. It's possible
2704 // for either of these sections to be present after the maps section right
2705 // now.
2706 // If the sections move around, this check might need to be modified.
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002707 match_str = android::base::StringPrintf(
Christopher Ferris3a0833c2023-07-28 13:07:53 -07002708 R"(\n--->Fault address falls at %s after any mapped regions\n(---------|\nopen files:))",
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002709 format_pointer(crash_uptr).c_str());
2710 ASSERT_MATCH(result, match_str);
2711}
2712
2713// Verify that a fault address between maps is properly handled.
2714TEST_F(CrasherTest, fault_address_between_maps) {
2715 // Create a map before the fork so it will be present in the child.
2716 void* start_ptr =
2717 mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2718 ASSERT_NE(MAP_FAILED, start_ptr);
2719 // Unmap the page in the middle.
2720 void* middle_ptr =
2721 reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start_ptr) + getpagesize());
2722 ASSERT_EQ(0, munmap(middle_ptr, getpagesize()));
2723
2724 StartProcess([middle_ptr]() {
2725 ASSERT_EQ(0, crash_call(reinterpret_cast<uintptr_t>(middle_ptr)));
2726 _exit(0);
2727 });
2728
2729 // Unmap the two maps.
2730 ASSERT_EQ(0, munmap(start_ptr, getpagesize()));
2731 void* end_ptr =
2732 reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start_ptr) + 2 * getpagesize());
2733 ASSERT_EQ(0, munmap(end_ptr, getpagesize()));
2734
2735 unique_fd output_fd;
2736 StartIntercept(&output_fd);
2737 FinishCrasher();
2738 AssertDeath(SIGSEGV);
2739
2740 int intercept_result;
2741 FinishIntercept(&intercept_result);
2742 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2743
2744 std::string result;
2745 ConsumeFd(std::move(output_fd), &result);
2746
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002747 std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x)";
2748 match_str += format_full_pointer(reinterpret_cast<uintptr_t>(middle_ptr));
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002749 ASSERT_MATCH(result, match_str);
2750
Ryan Prichardbc227032024-02-29 14:40:57 -08002751 ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002752
2753 match_str = android::base::StringPrintf(
2754 R"( %s.*\n--->Fault address falls at %s between mapped regions\n %s)",
2755 format_pointer(start_ptr).c_str(), format_pointer(middle_ptr).c_str(),
2756 format_pointer(end_ptr).c_str());
2757 ASSERT_MATCH(result, match_str);
2758}
2759
2760// Verify that a fault address happens in the correct map.
2761TEST_F(CrasherTest, fault_address_in_map) {
2762 // Create a map before the fork so it will be present in the child.
2763 void* ptr = mmap(nullptr, getpagesize(), 0, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2764 ASSERT_NE(MAP_FAILED, ptr);
2765
2766 StartProcess([ptr]() {
2767 ASSERT_EQ(0, crash_call(reinterpret_cast<uintptr_t>(ptr)));
2768 _exit(0);
2769 });
2770
2771 ASSERT_EQ(0, munmap(ptr, getpagesize()));
2772
2773 unique_fd output_fd;
2774 StartIntercept(&output_fd);
2775 FinishCrasher();
2776 AssertDeath(SIGSEGV);
2777
2778 int intercept_result;
2779 FinishIntercept(&intercept_result);
2780 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2781
2782 std::string result;
2783 ConsumeFd(std::move(output_fd), &result);
2784
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002785 std::string match_str = R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\), fault addr 0x)";
2786 match_str += format_full_pointer(reinterpret_cast<uintptr_t>(ptr));
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002787 ASSERT_MATCH(result, match_str);
2788
Ryan Prichardbc227032024-02-29 14:40:57 -08002789 ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002790
2791 match_str = android::base::StringPrintf(R"(\n--->%s.*\n)", format_pointer(ptr).c_str());
2792 ASSERT_MATCH(result, match_str);
2793}
Christopher Ferris2038cc72021-09-15 03:57:10 +00002794
2795static constexpr uint32_t kDexData[] = {
2796 0x0a786564, 0x00383330, 0xc98b3ab8, 0xf3749d94, 0xaecca4d8, 0xffc7b09a, 0xdca9ca7f, 0x5be5deab,
2797 0x00000220, 0x00000070, 0x12345678, 0x00000000, 0x00000000, 0x0000018c, 0x00000008, 0x00000070,
2798 0x00000004, 0x00000090, 0x00000002, 0x000000a0, 0x00000000, 0x00000000, 0x00000003, 0x000000b8,
2799 0x00000001, 0x000000d0, 0x00000130, 0x000000f0, 0x00000122, 0x0000012a, 0x00000132, 0x00000146,
2800 0x00000151, 0x00000154, 0x00000158, 0x0000016d, 0x00000001, 0x00000002, 0x00000004, 0x00000006,
2801 0x00000004, 0x00000002, 0x00000000, 0x00000005, 0x00000002, 0x0000011c, 0x00000000, 0x00000000,
2802 0x00010000, 0x00000007, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000,
2803 0x00000003, 0x00000000, 0x0000017e, 0x00000000, 0x00010001, 0x00000001, 0x00000173, 0x00000004,
2804 0x00021070, 0x000e0000, 0x00010001, 0x00000000, 0x00000178, 0x00000001, 0x0000000e, 0x00000001,
2805 0x3c060003, 0x74696e69, 0x4c06003e, 0x6e69614d, 0x4c12003b, 0x6176616a, 0x6e616c2f, 0x624f2f67,
2806 0x7463656a, 0x4d09003b, 0x2e6e6961, 0x6176616a, 0x00560100, 0x004c5602, 0x6a4c5b13, 0x2f617661,
2807 0x676e616c, 0x7274532f, 0x3b676e69, 0x616d0400, 0x01006e69, 0x000e0700, 0x07000103, 0x0000000e,
2808 0x81000002, 0x01f00480, 0x02880901, 0x0000000c, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
2809 0x00000008, 0x00000070, 0x00000002, 0x00000004, 0x00000090, 0x00000003, 0x00000002, 0x000000a0,
2810 0x00000005, 0x00000003, 0x000000b8, 0x00000006, 0x00000001, 0x000000d0, 0x00002001, 0x00000002,
2811 0x000000f0, 0x00001001, 0x00000001, 0x0000011c, 0x00002002, 0x00000008, 0x00000122, 0x00002003,
2812 0x00000002, 0x00000173, 0x00002000, 0x00000001, 0x0000017e, 0x00001000, 0x00000001, 0x0000018c,
2813};
2814
2815TEST_F(CrasherTest, verify_dex_pc_with_function_name) {
2816 StartProcess([]() {
2817 TemporaryDir td;
2818 std::string tmp_so_name;
2819 if (!CopySharedLibrary(td.path, &tmp_so_name)) {
2820 _exit(1);
2821 }
2822
2823 // In order to cause libunwindstack to look for this __dex_debug_descriptor
2824 // move the library to which has a basename of libart.so.
2825 std::string art_so_name = android::base::Dirname(tmp_so_name) + "/libart.so";
2826 ASSERT_EQ(0, rename(tmp_so_name.c_str(), art_so_name.c_str()));
2827 void* handle = dlopen(art_so_name.c_str(), RTLD_NOW | RTLD_LOCAL);
2828 if (handle == nullptr) {
2829 _exit(1);
2830 }
2831
2832 void* ptr =
2833 mmap(nullptr, sizeof(kDexData), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2834 ASSERT_TRUE(ptr != MAP_FAILED);
2835 memcpy(ptr, kDexData, sizeof(kDexData));
2836 prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, sizeof(kDexData), "dex");
2837
2838 JITCodeEntry dex_entry = {.symfile_addr = reinterpret_cast<uintptr_t>(ptr),
2839 .symfile_size = sizeof(kDexData)};
2840
2841 JITDescriptor* dex_debug =
2842 reinterpret_cast<JITDescriptor*>(dlsym(handle, "__dex_debug_descriptor"));
2843 ASSERT_TRUE(dex_debug != nullptr);
2844 dex_debug->version = 1;
2845 dex_debug->action_flag = 0;
2846 dex_debug->relevant_entry = 0;
2847 dex_debug->first_entry = reinterpret_cast<uintptr_t>(&dex_entry);
2848
2849 // This sets the magic dex pc value for register 0, using the value
2850 // of register 1 + 0x102.
2851 asm(".cfi_escape "
2852 "0x16 /* DW_CFA_val_expression */, 0, 0x0a /* size */,"
2853 "0x0c /* DW_OP_const4u */, 0x44, 0x45, 0x58, 0x31, /* magic = 'DEX1' */"
2854 "0x13 /* DW_OP_drop */,"
2855 "0x92 /* DW_OP_bregx */, 1, 0x82, 0x02 /* 2-byte SLEB128 */");
2856
2857 // For each different architecture, set register one to the dex ptr mmap
2858 // created above. Then do a nullptr dereference to force a crash.
2859#if defined(__arm__)
2860 asm volatile(
2861 "mov r1, %[base]\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002862 "mov r2, #0\n"
2863 "str r2, [r2]\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002864 : [base] "+r"(ptr)
2865 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002866 : "r1", "r2", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002867#elif defined(__aarch64__)
2868 asm volatile(
2869 "mov x1, %[base]\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002870 "mov x2, #0\n"
2871 "str xzr, [x2]\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002872 : [base] "+r"(ptr)
2873 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002874 : "x1", "x2", "memory");
2875#elif defined(__riscv)
2876 // TODO: x1 is ra (the link register) on riscv64, so this might have
2877 // unintended consequences, but we'll need to change the .cfi_escape if so.
2878 asm volatile(
2879 "mv x1, %[base]\n"
2880 "sw zero, 0(zero)\n"
2881 : [base] "+r"(ptr)
2882 :
2883 : "x1", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002884#elif defined(__i386__)
2885 asm volatile(
2886 "mov %[base], %%ecx\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002887 "movl $0, 0\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002888 : [base] "+r"(ptr)
2889 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002890 : "ecx", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002891#elif defined(__x86_64__)
2892 asm volatile(
2893 "mov %[base], %%rdx\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002894 "movq $0, 0\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002895 : [base] "+r"(ptr)
2896 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002897 : "rdx", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002898#else
2899#error "Unsupported architecture"
2900#endif
2901 _exit(0);
2902 });
2903
2904 unique_fd output_fd;
2905 StartIntercept(&output_fd);
2906 FinishCrasher();
2907 AssertDeath(SIGSEGV);
2908
2909 int intercept_result;
2910 FinishIntercept(&intercept_result);
2911 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2912
2913 std::string result;
2914 ConsumeFd(std::move(output_fd), &result);
2915
2916 // Verify the process crashed properly.
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002917 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0*)");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002918
2919 // Now verify that the dex_pc frame includes a proper function name.
2920 ASSERT_MATCH(result, R"( \[anon:dex\] \(Main\.\<init\>\+2)");
2921}
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00002922
2923static std::string format_map_pointer(uintptr_t ptr) {
2924#if defined(__LP64__)
2925 return android::base::StringPrintf("%08x'%08x", static_cast<uint32_t>(ptr >> 32),
2926 static_cast<uint32_t>(ptr & 0xffffffff));
2927#else
2928 return android::base::StringPrintf("%08x", ptr);
2929#endif
2930}
2931
2932// Verify that map data is properly formatted.
2933TEST_F(CrasherTest, verify_map_format) {
2934 // Create multiple maps to make sure that the map data is formatted properly.
2935 void* none_map = mmap(nullptr, getpagesize(), 0, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2936 ASSERT_NE(MAP_FAILED, none_map);
2937 void* r_map = mmap(nullptr, getpagesize(), PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2938 ASSERT_NE(MAP_FAILED, r_map);
2939 void* w_map = mmap(nullptr, getpagesize(), PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2940 ASSERT_NE(MAP_FAILED, w_map);
2941 void* x_map = mmap(nullptr, getpagesize(), PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2942 ASSERT_NE(MAP_FAILED, x_map);
2943
2944 TemporaryFile tf;
2945 ASSERT_EQ(0x2000, lseek(tf.fd, 0x2000, SEEK_SET));
2946 char c = 'f';
2947 ASSERT_EQ(1, write(tf.fd, &c, 1));
2948 ASSERT_EQ(0x5000, lseek(tf.fd, 0x5000, SEEK_SET));
2949 ASSERT_EQ(1, write(tf.fd, &c, 1));
2950 ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
2951 void* file_map = mmap(nullptr, 0x3001, PROT_READ, MAP_PRIVATE, tf.fd, 0x2000);
2952 ASSERT_NE(MAP_FAILED, file_map);
2953
2954 StartProcess([]() { abort(); });
2955
2956 ASSERT_EQ(0, munmap(none_map, getpagesize()));
2957 ASSERT_EQ(0, munmap(r_map, getpagesize()));
2958 ASSERT_EQ(0, munmap(w_map, getpagesize()));
2959 ASSERT_EQ(0, munmap(x_map, getpagesize()));
2960 ASSERT_EQ(0, munmap(file_map, 0x3001));
2961
2962 unique_fd output_fd;
2963 StartIntercept(&output_fd);
2964 FinishCrasher();
2965 AssertDeath(SIGABRT);
2966 int intercept_result;
2967 FinishIntercept(&intercept_result);
2968
2969 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2970
2971 std::string result;
2972 ConsumeFd(std::move(output_fd), &result);
2973
2974 std::string match_str;
2975 // Verify none.
2976 match_str = android::base::StringPrintf(
2977 " %s-%s --- 0 1000\\n",
2978 format_map_pointer(reinterpret_cast<uintptr_t>(none_map)).c_str(),
2979 format_map_pointer(reinterpret_cast<uintptr_t>(none_map) + getpagesize() - 1).c_str());
2980 ASSERT_MATCH(result, match_str);
2981
2982 // Verify read-only.
2983 match_str = android::base::StringPrintf(
2984 " %s-%s r-- 0 1000\\n",
2985 format_map_pointer(reinterpret_cast<uintptr_t>(r_map)).c_str(),
2986 format_map_pointer(reinterpret_cast<uintptr_t>(r_map) + getpagesize() - 1).c_str());
2987 ASSERT_MATCH(result, match_str);
2988
2989 // Verify write-only.
2990 match_str = android::base::StringPrintf(
2991 " %s-%s -w- 0 1000\\n",
2992 format_map_pointer(reinterpret_cast<uintptr_t>(w_map)).c_str(),
2993 format_map_pointer(reinterpret_cast<uintptr_t>(w_map) + getpagesize() - 1).c_str());
2994 ASSERT_MATCH(result, match_str);
2995
2996 // Verify exec-only.
2997 match_str = android::base::StringPrintf(
2998 " %s-%s --x 0 1000\\n",
2999 format_map_pointer(reinterpret_cast<uintptr_t>(x_map)).c_str(),
3000 format_map_pointer(reinterpret_cast<uintptr_t>(x_map) + getpagesize() - 1).c_str());
3001 ASSERT_MATCH(result, match_str);
3002
3003 // Verify file map with non-zero offset and a name.
3004 match_str = android::base::StringPrintf(
3005 " %s-%s r-- 2000 4000 %s\\n",
3006 format_map_pointer(reinterpret_cast<uintptr_t>(file_map)).c_str(),
3007 format_map_pointer(reinterpret_cast<uintptr_t>(file_map) + 0x3fff).c_str(), tf.path);
3008 ASSERT_MATCH(result, match_str);
3009}
3010
3011// Verify that the tombstone map data is correct.
3012TEST_F(CrasherTest, verify_header) {
3013 StartProcess([]() { abort(); });
3014
3015 unique_fd output_fd;
3016 StartIntercept(&output_fd);
3017 FinishCrasher();
3018 AssertDeath(SIGABRT);
3019 int intercept_result;
3020 FinishIntercept(&intercept_result);
3021
3022 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3023
3024 std::string result;
3025 ConsumeFd(std::move(output_fd), &result);
3026
3027 std::string match_str = android::base::StringPrintf(
3028 "Build fingerprint: '%s'\\nRevision: '%s'\\n",
3029 android::base::GetProperty("ro.build.fingerprint", "unknown").c_str(),
3030 android::base::GetProperty("ro.revision", "unknown").c_str());
3031 match_str += android::base::StringPrintf("ABI: '%s'\n", ABI_STRING);
3032 ASSERT_MATCH(result, match_str);
3033}
3034
3035// Verify that the thread header is formatted properly.
3036TEST_F(CrasherTest, verify_thread_header) {
3037 void* shared_map =
3038 mmap(nullptr, sizeof(pid_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
3039 ASSERT_NE(MAP_FAILED, shared_map);
3040 memset(shared_map, 0, sizeof(pid_t));
3041
3042 StartProcess([&shared_map]() {
3043 std::atomic_bool tid_written;
3044 std::thread thread([&tid_written, &shared_map]() {
3045 pid_t tid = gettid();
3046 memcpy(shared_map, &tid, sizeof(pid_t));
3047 tid_written = true;
3048 volatile bool done = false;
3049 while (!done)
3050 ;
3051 });
3052 thread.detach();
3053 while (!tid_written.load(std::memory_order_acquire))
3054 ;
3055 abort();
3056 });
3057
3058 pid_t primary_pid = crasher_pid;
3059
3060 unique_fd output_fd;
3061 StartIntercept(&output_fd);
3062 FinishCrasher();
3063 AssertDeath(SIGABRT);
3064 int intercept_result;
3065 FinishIntercept(&intercept_result);
3066 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3067
3068 // Read the tid data out.
3069 pid_t tid;
3070 memcpy(&tid, shared_map, sizeof(pid_t));
3071 ASSERT_NE(0, tid);
3072
3073 ASSERT_EQ(0, munmap(shared_map, sizeof(pid_t)));
3074
3075 std::string result;
3076 ConsumeFd(std::move(output_fd), &result);
3077
3078 // Verify that there are two headers, one where the tid is "primary_pid"
3079 // and the other where the tid is "tid".
3080 std::string match_str = android::base::StringPrintf("pid: %d, tid: %d, name: .* >>> .* <<<\\n",
3081 primary_pid, primary_pid);
3082 ASSERT_MATCH(result, match_str);
3083
3084 match_str =
3085 android::base::StringPrintf("pid: %d, tid: %d, name: .* >>> .* <<<\\n", primary_pid, tid);
3086 ASSERT_MATCH(result, match_str);
3087}
3088
3089// Verify that there is a BuildID present in the map section and set properly.
3090TEST_F(CrasherTest, verify_build_id) {
3091 StartProcess([]() { abort(); });
3092
3093 unique_fd output_fd;
3094 StartIntercept(&output_fd);
3095 FinishCrasher();
3096 AssertDeath(SIGABRT);
3097 int intercept_result;
3098 FinishIntercept(&intercept_result);
3099 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3100
3101 std::string result;
3102 ConsumeFd(std::move(output_fd), &result);
3103
3104 // Find every /system or /apex lib and verify the BuildID is displayed
3105 // properly.
3106 bool found_valid_elf = false;
3107 std::smatch match;
3108 std::regex build_id_regex(R"( ((/system/|/apex/)\S+) \(BuildId: ([^\)]+)\))");
3109 for (std::string prev_file; std::regex_search(result, match, build_id_regex);
3110 result = match.suffix()) {
3111 if (prev_file == match[1]) {
3112 // Already checked this file.
3113 continue;
3114 }
3115
3116 prev_file = match[1];
Christopher Ferris15038902023-11-10 00:05:49 -08003117 auto elf_memory = unwindstack::Memory::CreateFileMemory(prev_file, 0);
3118 unwindstack::Elf elf(elf_memory);
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00003119 if (!elf.Init() || !elf.valid()) {
3120 // Skipping invalid elf files.
3121 continue;
3122 }
3123 ASSERT_EQ(match[3], elf.GetPrintableBuildID());
3124
3125 found_valid_elf = true;
3126 }
3127 ASSERT_TRUE(found_valid_elf) << "Did not find any elf files with valid BuildIDs to check.";
3128}
Christopher Ferrisbda10642023-04-24 18:14:53 -07003129
3130const char kLogMessage[] = "Should not see this log message.";
3131
3132// Verify that the logd process does not read the log.
3133TEST_F(CrasherTest, logd_skips_reading_logs) {
3134 StartProcess([]() {
3135 pthread_setname_np(pthread_self(), "logd");
3136 LOG(INFO) << kLogMessage;
3137 abort();
3138 });
3139
3140 unique_fd output_fd;
3141 StartIntercept(&output_fd);
3142 FinishCrasher();
3143 AssertDeath(SIGABRT);
3144 int intercept_result;
3145 FinishIntercept(&intercept_result);
3146 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3147
3148 std::string result;
3149 ConsumeFd(std::move(output_fd), &result);
3150 // logd should not contain our log message.
3151 ASSERT_NOT_MATCH(result, kLogMessage);
3152}
3153
3154// Verify that the logd process does not read the log when the non-main
3155// thread crashes.
3156TEST_F(CrasherTest, logd_skips_reading_logs_not_main_thread) {
3157 StartProcess([]() {
3158 pthread_setname_np(pthread_self(), "logd");
3159 LOG(INFO) << kLogMessage;
3160
3161 std::thread thread([]() {
3162 pthread_setname_np(pthread_self(), "not_logd_thread");
3163 // Raise the signal on the side thread.
3164 raise_debugger_signal(kDebuggerdTombstone);
3165 });
3166 thread.join();
3167 _exit(0);
3168 });
3169
3170 unique_fd output_fd;
3171 StartIntercept(&output_fd, kDebuggerdTombstone);
3172 FinishCrasher();
3173 AssertDeath(0);
3174
3175 int intercept_result;
3176 FinishIntercept(&intercept_result);
3177 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3178
3179 std::string result;
3180 ConsumeFd(std::move(output_fd), &result);
3181 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
3182 ASSERT_NOT_MATCH(result, kLogMessage);
3183}
Christopher Ferris98d62422023-05-24 20:01:10 +00003184
3185// Disable this test since there is a high liklihood that this would
3186// be flaky since it requires 500 messages being in the log.
3187TEST_F(CrasherTest, DISABLED_max_log_messages) {
3188 StartProcess([]() {
3189 for (size_t i = 0; i < 600; i++) {
3190 LOG(INFO) << "Message number " << i;
3191 }
3192 abort();
3193 });
3194
3195 unique_fd output_fd;
3196 StartIntercept(&output_fd);
3197 FinishCrasher();
3198 AssertDeath(SIGABRT);
3199 int intercept_result;
3200 FinishIntercept(&intercept_result);
3201 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3202
3203 std::string result;
3204 ConsumeFd(std::move(output_fd), &result);
3205 ASSERT_NOT_MATCH(result, "Message number 99");
3206 ASSERT_MATCH(result, "Message number 100");
3207 ASSERT_MATCH(result, "Message number 599");
3208}
3209
3210TEST_F(CrasherTest, log_with_newline) {
3211 StartProcess([]() {
3212 LOG(INFO) << "This line has a newline.\nThis is on the next line.";
3213 abort();
3214 });
3215
3216 unique_fd output_fd;
3217 StartIntercept(&output_fd);
3218 FinishCrasher();
3219 AssertDeath(SIGABRT);
3220 int intercept_result;
3221 FinishIntercept(&intercept_result);
3222 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3223
3224 std::string result;
3225 ConsumeFd(std::move(output_fd), &result);
3226 ASSERT_MATCH(result, ":\\s*This line has a newline.");
3227 ASSERT_MATCH(result, ":\\s*This is on the next line.");
3228}