blob: e4e2f99cc28cf1e0587b327b7098cfb24db84591 [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);
Xiaohui Niu7bfbe412024-04-26 11:08:15 +08001670 ASSERT_MATCH(
1671 result,
1672 R"(signal 6 \(SIGABRT\))");
Christopher Ferris303c6be2022-05-24 17:08:33 -07001673 ASSERT_BACKTRACE_FRAME(result, "abort");
1674}
1675
Christopher Ferris7c2e7e32022-05-27 12:57:58 -07001676TEST_F(CrasherTest, seccomp_tombstone_multiple_threads_abort) {
1677 int intercept_result;
1678 unique_fd output_fd;
1679
1680 static const auto dump_type = kDebuggerdTombstone;
1681 StartProcess(
1682 []() {
1683 std::thread a(foo);
1684 std::thread b(bar);
1685
1686 std::this_thread::sleep_for(100ms);
1687
1688 std::thread abort_thread([] { abort(); });
1689 abort_thread.join();
1690 },
1691 &seccomp_fork);
1692
1693 StartIntercept(&output_fd, dump_type);
1694 FinishCrasher();
1695 AssertDeath(SIGABRT);
1696 FinishIntercept(&intercept_result);
1697 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1698
1699 std::string result;
1700 ConsumeFd(std::move(output_fd), &result);
1701 ASSERT_BACKTRACE_FRAME(result, "abort");
1702 ASSERT_BACKTRACE_FRAME(result, "foo");
1703 ASSERT_BACKTRACE_FRAME(result, "bar");
1704 ASSERT_BACKTRACE_FRAME(result, "main");
1705}
1706
Josh Gaoe04ca272018-01-16 15:38:17 -08001707TEST_F(CrasherTest, seccomp_backtrace) {
1708 int intercept_result;
1709 unique_fd output_fd;
1710
1711 static const auto dump_type = kDebuggerdNativeBacktrace;
1712 StartProcess(
1713 []() {
Josh Gao6f9eeec2018-09-12 13:55:47 -07001714 std::thread a(foo);
1715 std::thread b(bar);
1716
1717 std::this_thread::sleep_for(100ms);
1718
Josh Gaoe04ca272018-01-16 15:38:17 -08001719 raise_debugger_signal(dump_type);
1720 _exit(0);
1721 },
1722 &seccomp_fork);
1723
1724 StartIntercept(&output_fd, dump_type);
1725 FinishCrasher();
1726 AssertDeath(0);
1727 FinishIntercept(&intercept_result);
1728 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1729
1730 std::string result;
1731 ConsumeFd(std::move(output_fd), &result);
1732 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
Josh Gao6f9eeec2018-09-12 13:55:47 -07001733 ASSERT_BACKTRACE_FRAME(result, "foo");
1734 ASSERT_BACKTRACE_FRAME(result, "bar");
Josh Gaoe04ca272018-01-16 15:38:17 -08001735}
1736
Christopher Ferris7c2e7e32022-05-27 12:57:58 -07001737TEST_F(CrasherTest, seccomp_backtrace_from_thread) {
1738 int intercept_result;
1739 unique_fd output_fd;
1740
1741 static const auto dump_type = kDebuggerdNativeBacktrace;
1742 StartProcess(
1743 []() {
1744 std::thread a(foo);
1745 std::thread b(bar);
1746
1747 std::this_thread::sleep_for(100ms);
1748
1749 std::thread raise_thread([] {
1750 raise_debugger_signal(dump_type);
1751 _exit(0);
1752 });
1753 raise_thread.join();
1754 },
1755 &seccomp_fork);
1756
1757 StartIntercept(&output_fd, dump_type);
1758 FinishCrasher();
1759 AssertDeath(0);
1760 FinishIntercept(&intercept_result);
1761 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1762
1763 std::string result;
1764 ConsumeFd(std::move(output_fd), &result);
1765 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
1766 ASSERT_BACKTRACE_FRAME(result, "foo");
1767 ASSERT_BACKTRACE_FRAME(result, "bar");
1768 ASSERT_BACKTRACE_FRAME(result, "main");
1769}
1770
Josh Gaoe04ca272018-01-16 15:38:17 -08001771TEST_F(CrasherTest, seccomp_crash_logcat) {
1772 StartProcess([]() { abort(); }, &seccomp_fork);
1773 FinishCrasher();
1774
1775 // Make sure we don't get SIGSYS when trying to dump a crash to logcat.
1776 AssertDeath(SIGABRT);
1777}
1778
Josh Gaofd13bf02017-08-18 15:37:26 -07001779TEST_F(CrasherTest, competing_tracer) {
1780 int intercept_result;
1781 unique_fd output_fd;
1782 StartProcess([]() {
Josh Gao2b2ae0c2017-08-21 14:31:17 -07001783 raise(SIGABRT);
Josh Gaofd13bf02017-08-18 15:37:26 -07001784 });
1785
1786 StartIntercept(&output_fd);
Josh Gaofd13bf02017-08-18 15:37:26 -07001787
1788 ASSERT_EQ(0, ptrace(PTRACE_SEIZE, crasher_pid, 0, 0));
Josh Gao2b2ae0c2017-08-21 14:31:17 -07001789 FinishCrasher();
Josh Gaofd13bf02017-08-18 15:37:26 -07001790
1791 int status;
Christopher Ferris172b0a02019-09-18 17:48:30 -07001792 ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
Josh Gaofd13bf02017-08-18 15:37:26 -07001793 ASSERT_TRUE(WIFSTOPPED(status));
1794 ASSERT_EQ(SIGABRT, WSTOPSIG(status));
1795
1796 ASSERT_EQ(0, ptrace(PTRACE_CONT, crasher_pid, 0, SIGABRT));
1797 FinishIntercept(&intercept_result);
1798 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1799
1800 std::string result;
1801 ConsumeFd(std::move(output_fd), &result);
1802 std::string regex = R"(failed to attach to thread \d+, already traced by )";
1803 regex += std::to_string(gettid());
1804 regex += R"( \(.+debuggerd_test)";
1805 ASSERT_MATCH(result, regex.c_str());
1806
Christopher Ferris172b0a02019-09-18 17:48:30 -07001807 ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
Josh Gao2b2ae0c2017-08-21 14:31:17 -07001808 ASSERT_TRUE(WIFSTOPPED(status));
1809 ASSERT_EQ(SIGABRT, WSTOPSIG(status));
1810
Josh Gaofd13bf02017-08-18 15:37:26 -07001811 ASSERT_EQ(0, ptrace(PTRACE_DETACH, crasher_pid, 0, SIGABRT));
1812 AssertDeath(SIGABRT);
1813}
1814
Mitch Phillips18ce5422023-01-19 14:23:49 -08001815struct GwpAsanTestParameters {
1816 size_t alloc_size;
1817 bool free_before_access;
1818 int access_offset;
1819 std::string cause_needle; // Needle to be found in the "Cause: [GWP-ASan]" line.
1820};
1821
1822struct GwpAsanCrasherTest
1823 : CrasherTest,
1824 testing::WithParamInterface<
1825 std::tuple<GwpAsanTestParameters, /* recoverable */ bool, /* seccomp */ bool>> {};
1826
1827GwpAsanTestParameters gwp_asan_tests[] = {
1828 {/* alloc_size */ 7, /* free_before_access */ true, /* access_offset */ 0,
1829 "Use After Free, 0 bytes into a 7-byte allocation"},
1830 {/* alloc_size */ 15, /* free_before_access */ true, /* access_offset */ 1,
1831 "Use After Free, 1 byte into a 15-byte allocation"},
1832 {/* alloc_size */ 4096, /* free_before_access */ false, /* access_offset */ 4098,
1833 "Buffer Overflow, 2 bytes right of a 4096-byte allocation"},
1834 {/* alloc_size */ 4096, /* free_before_access */ false, /* access_offset */ -1,
1835 "Buffer Underflow, 1 byte left of a 4096-byte allocation"},
1836};
1837
1838INSTANTIATE_TEST_SUITE_P(
1839 GwpAsanTests, GwpAsanCrasherTest,
1840 testing::Combine(testing::ValuesIn(gwp_asan_tests),
1841 /* recoverable */ testing::Bool(),
1842 /* seccomp */ testing::Bool()),
1843 [](const testing::TestParamInfo<
1844 std::tuple<GwpAsanTestParameters, /* recoverable */ bool, /* seccomp */ bool>>& info) {
1845 const GwpAsanTestParameters& params = std::get<0>(info.param);
1846 std::string name = params.free_before_access ? "UseAfterFree" : "Overflow";
1847 name += testing::PrintToString(params.alloc_size);
1848 name += "Alloc";
1849 if (params.access_offset < 0) {
1850 name += "Left";
1851 name += testing::PrintToString(params.access_offset * -1);
1852 } else {
1853 name += "Right";
1854 name += testing::PrintToString(params.access_offset);
1855 }
1856 name += "Bytes";
1857 if (std::get<1>(info.param)) name += "Recoverable";
1858 if (std::get<2>(info.param)) name += "Seccomp";
1859 return name;
1860 });
1861
1862TEST_P(GwpAsanCrasherTest, run_gwp_asan_test) {
1863 if (mte_supported()) {
1864 // Skip this test on MTE hardware, as MTE will reliably catch these errors
1865 // instead of GWP-ASan.
1866 GTEST_SKIP() << "Skipped on MTE.";
1867 }
1868 // Skip this test on HWASan, which will reliably catch test errors as well.
1869 SKIP_WITH_HWASAN;
1870
1871 GwpAsanTestParameters params = std::get<0>(GetParam());
1872 bool recoverable = std::get<1>(GetParam());
1873 LogcatCollector logcat_collector;
1874
1875 int intercept_result;
1876 unique_fd output_fd;
1877 StartProcess([&recoverable]() {
1878 const char* env[] = {"GWP_ASAN_SAMPLE_RATE=1", "GWP_ASAN_PROCESS_SAMPLING=1",
1879 "GWP_ASAN_MAX_ALLOCS=40000", nullptr, nullptr};
Mitch Phillipsa2f53352024-04-09 15:59:12 +02001880 if (!recoverable) {
1881 env[3] = "GWP_ASAN_RECOVERABLE=false";
Mitch Phillips18ce5422023-01-19 14:23:49 -08001882 }
1883 std::string test_name = ::testing::UnitTest::GetInstance()->current_test_info()->name();
1884 test_name = std::regex_replace(test_name, std::regex("run_gwp_asan_test"),
1885 "DISABLED_run_gwp_asan_test");
1886 std::string test_filter = "--gtest_filter=*";
1887 test_filter += test_name;
1888 std::string this_binary = android::base::GetExecutablePath();
1889 const char* args[] = {this_binary.c_str(), "--gtest_also_run_disabled_tests",
1890 test_filter.c_str(), nullptr};
1891 // We check the crash report from a debuggerd handler and from logcat. The
1892 // echo from stdout/stderr of the subprocess trips up atest, because it
1893 // doesn't like that two tests started in a row without the first one
1894 // finishing (even though the second one is in a subprocess).
1895 close(STDOUT_FILENO);
1896 close(STDERR_FILENO);
1897 execve(this_binary.c_str(), const_cast<char**>(args), const_cast<char**>(env));
1898 });
1899
1900 StartIntercept(&output_fd);
1901 FinishCrasher();
1902 if (recoverable) {
1903 AssertDeath(0);
1904 } else {
1905 AssertDeath(SIGSEGV);
1906 }
1907 FinishIntercept(&intercept_result);
1908
1909 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1910
1911 std::vector<std::string> log_sources(2);
1912 ConsumeFd(std::move(output_fd), &log_sources[0]);
1913 logcat_collector.Collect(&log_sources[1]);
1914
1915 // seccomp forces the fallback handler, which doesn't print GWP-ASan debugging
1916 // information. Make sure the recovery still works, but the report won't be
1917 // hugely useful, it looks like a regular SEGV.
1918 bool seccomp = std::get<2>(GetParam());
1919 if (!seccomp) {
1920 for (const auto& result : log_sources) {
1921 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\))");
1922 ASSERT_MATCH(result, R"(Cause: \[GWP-ASan\]: )" + params.cause_needle);
1923 if (params.free_before_access) {
1924 ASSERT_MATCH(result, R"(deallocated by thread .*\n.*#00 pc)");
1925 }
1926 ASSERT_MATCH(result, R"((^|\s)allocated by thread .*\n.*#00 pc)");
1927 }
1928 }
1929}
1930
1931TEST_P(GwpAsanCrasherTest, DISABLED_run_gwp_asan_test) {
1932 GwpAsanTestParameters params = std::get<0>(GetParam());
1933 bool seccomp = std::get<2>(GetParam());
1934 if (seccomp) {
1935 ScopedMinijail jail{minijail_new()};
1936 setup_jail(jail.get());
1937 minijail_enter(jail.get());
1938 }
1939
1940 // Use 'volatile' to prevent a very clever compiler eliminating the store.
1941 char* volatile p = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1942 if (params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
1943 p[params.access_offset] = 42;
1944 if (!params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
Mitch Phillips70aa2192023-02-22 11:31:36 -08001945
1946 bool recoverable = std::get<1>(GetParam());
1947 ASSERT_TRUE(recoverable); // Non-recoverable should have crashed.
1948
1949 // As we're in recoverable mode, trigger another 2x use-after-frees (ensuring
1950 // we end with at least one in a different slot), make sure the process still
1951 // doesn't crash.
1952 p = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1953 char* volatile p2 = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1954 free(static_cast<void*>(const_cast<char*>(p)));
1955 free(static_cast<void*>(const_cast<char*>(p2)));
1956 *p = 42;
1957 *p2 = 42;
1958
1959 // Under clang coverage (which is a default TEST_MAPPING presubmit target), the
1960 // recoverable+seccomp tests fail because the minijail prevents some atexit syscalls that clang
1961 // coverage does. Thus, skip the atexit handlers.
1962 _exit(0);
Mitch Phillips18ce5422023-01-19 14:23:49 -08001963}
1964
Josh Gaobf06a402018-08-27 16:34:01 -07001965TEST_F(CrasherTest, fdsan_warning_abort_message) {
1966 int intercept_result;
1967 unique_fd output_fd;
1968
1969 StartProcess([]() {
1970 android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
Christopher Ferris172b0a02019-09-18 17:48:30 -07001971 unique_fd fd(TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY | O_CLOEXEC)));
Josh Gaobf06a402018-08-27 16:34:01 -07001972 if (fd == -1) {
1973 abort();
1974 }
1975 close(fd.get());
1976 _exit(0);
1977 });
1978
1979 StartIntercept(&output_fd);
1980 FinishCrasher();
1981 AssertDeath(0);
1982 FinishIntercept(&intercept_result);
1983 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1984
1985 std::string result;
1986 ConsumeFd(std::move(output_fd), &result);
1987 ASSERT_MATCH(result, "Abort message: 'attempted to close");
1988}
1989
Josh Gaoc3c8c022017-02-13 16:36:18 -08001990TEST(crash_dump, zombie) {
1991 pid_t forkpid = fork();
1992
Josh Gaoc3c8c022017-02-13 16:36:18 -08001993 pid_t rc;
1994 int status;
1995
1996 if (forkpid == 0) {
1997 errno = 0;
1998 rc = waitpid(-1, &status, WNOHANG | __WALL | __WNOTHREAD);
1999 if (rc != -1 || errno != ECHILD) {
2000 errx(2, "first waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
2001 }
2002
Josh Gaoa48b41b2019-12-13 14:11:04 -08002003 raise(BIONIC_SIGNAL_DEBUGGER);
Josh Gaoc3c8c022017-02-13 16:36:18 -08002004
2005 errno = 0;
Christopher Ferris172b0a02019-09-18 17:48:30 -07002006 rc = TEMP_FAILURE_RETRY(waitpid(-1, &status, __WALL | __WNOTHREAD));
Josh Gaoc3c8c022017-02-13 16:36:18 -08002007 if (rc != -1 || errno != ECHILD) {
2008 errx(2, "second waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
2009 }
2010 _exit(0);
2011 } else {
Christopher Ferris172b0a02019-09-18 17:48:30 -07002012 rc = TEMP_FAILURE_RETRY(waitpid(forkpid, &status, 0));
Josh Gaoc3c8c022017-02-13 16:36:18 -08002013 ASSERT_EQ(forkpid, rc);
2014 ASSERT_TRUE(WIFEXITED(status));
2015 ASSERT_EQ(0, WEXITSTATUS(status));
2016 }
2017}
Josh Gao352a8452017-03-30 16:46:21 -07002018
2019TEST(tombstoned, no_notify) {
2020 // Do this a few times.
2021 for (int i = 0; i < 3; ++i) {
2022 pid_t pid = 123'456'789 + i;
2023
2024 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002025 InterceptResponse response = {};
2026 tombstoned_intercept(pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2027 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2028 << "Error message: " << response.error_message;
Josh Gao352a8452017-03-30 16:46:21 -07002029
2030 {
2031 unique_fd tombstoned_socket, input_fd;
Narayan Kamatha73df602017-05-24 15:07:25 +01002032 ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
Josh Gao352a8452017-03-30 16:46:21 -07002033 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid)));
2034 }
2035
2036 pid_t read_pid;
2037 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid)));
2038 ASSERT_EQ(read_pid, pid);
2039 }
2040}
2041
2042TEST(tombstoned, stress) {
2043 // Spawn threads to simultaneously do a bunch of failing dumps and a bunch of successful dumps.
2044 static constexpr int kDumpCount = 100;
2045
2046 std::atomic<bool> start(false);
2047 std::vector<std::thread> threads;
2048 threads.emplace_back([&start]() {
2049 while (!start) {
2050 continue;
2051 }
2052
2053 // Use a way out of range pid, to avoid stomping on an actual process.
2054 pid_t pid_base = 1'000'000;
2055
2056 for (int dump = 0; dump < kDumpCount; ++dump) {
2057 pid_t pid = pid_base + dump;
2058
2059 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002060 InterceptResponse response = {};
2061 tombstoned_intercept(pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2062 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2063 << "Error messeage: " << response.error_message;
Josh Gao352a8452017-03-30 16:46:21 -07002064
2065 // Pretend to crash, and then immediately close the socket.
2066 unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName,
2067 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
2068 if (sockfd == -1) {
2069 FAIL() << "failed to connect to tombstoned: " << strerror(errno);
2070 }
2071 TombstonedCrashPacket packet = {};
2072 packet.packet_type = CrashPacketType::kDumpRequest;
2073 packet.packet.dump_request.pid = pid;
2074 if (TEMP_FAILURE_RETRY(write(sockfd, &packet, sizeof(packet))) != sizeof(packet)) {
2075 FAIL() << "failed to write to tombstoned: " << strerror(errno);
2076 }
2077
2078 continue;
2079 }
2080 });
2081
2082 threads.emplace_back([&start]() {
2083 while (!start) {
2084 continue;
2085 }
2086
2087 // Use a way out of range pid, to avoid stomping on an actual process.
2088 pid_t pid_base = 2'000'000;
2089
2090 for (int dump = 0; dump < kDumpCount; ++dump) {
2091 pid_t pid = pid_base + dump;
2092
2093 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002094 InterceptResponse response = {};
2095 tombstoned_intercept(pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2096 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2097 << "Error message: " << response.error_message;
Josh Gao352a8452017-03-30 16:46:21 -07002098
2099 {
2100 unique_fd tombstoned_socket, input_fd;
Narayan Kamatha73df602017-05-24 15:07:25 +01002101 ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
Josh Gao352a8452017-03-30 16:46:21 -07002102 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid)));
2103 tombstoned_notify_completion(tombstoned_socket.get());
2104 }
2105
2106 // TODO: Fix the race that requires this sleep.
2107 std::this_thread::sleep_for(50ms);
2108
2109 pid_t read_pid;
2110 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid)));
2111 ASSERT_EQ(read_pid, pid);
2112 }
2113 });
2114
2115 start = true;
2116
2117 for (std::thread& thread : threads) {
2118 thread.join();
2119 }
2120}
Narayan Kamathca5e9082017-06-02 15:42:06 +01002121
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002122TEST(tombstoned, intercept_java_trace_smoke) {
Narayan Kamathca5e9082017-06-02 15:42:06 +01002123 // Using a "real" PID is a little dangerous here - if the test fails
2124 // or crashes, we might end up getting a bogus / unreliable stack
2125 // trace.
2126 const pid_t self = getpid();
2127
2128 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002129 InterceptResponse response = {};
2130 tombstoned_intercept(self, &intercept_fd, &output_fd, &response, kDebuggerdJavaBacktrace);
2131 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2132 << "Error message: " << response.error_message;
Narayan Kamathca5e9082017-06-02 15:42:06 +01002133
Josh Gao76e1e302021-01-26 15:53:11 -08002134 // First connect to tombstoned requesting a native tombstone. This
Narayan Kamathca5e9082017-06-02 15:42:06 +01002135 // should result in a "regular" FD and not the installed intercept.
2136 const char native[] = "native";
2137 unique_fd tombstoned_socket, input_fd;
Josh Gao76e1e302021-01-26 15:53:11 -08002138 ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
Narayan Kamathca5e9082017-06-02 15:42:06 +01002139 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), native, sizeof(native)));
2140 tombstoned_notify_completion(tombstoned_socket.get());
2141
2142 // Then, connect to tombstoned asking for a java backtrace. This *should*
2143 // trigger the intercept.
2144 const char java[] = "java";
2145 ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdJavaBacktrace));
2146 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), java, sizeof(java)));
2147 tombstoned_notify_completion(tombstoned_socket.get());
2148
2149 char outbuf[sizeof(java)];
2150 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
2151 ASSERT_STREQ("java", outbuf);
2152}
2153
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002154TEST(tombstoned, intercept_multiple_dump_types) {
Narayan Kamathca5e9082017-06-02 15:42:06 +01002155 const pid_t fake_pid = 1'234'567;
2156 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002157 InterceptResponse response = {};
2158 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdJavaBacktrace);
2159 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2160 << "Error message: " << response.error_message;
Narayan Kamathca5e9082017-06-02 15:42:06 +01002161
2162 unique_fd intercept_fd_2, output_fd_2;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002163 tombstoned_intercept(fake_pid, &intercept_fd_2, &output_fd_2, &response,
2164 kDebuggerdNativeBacktrace);
2165 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2166 << "Error message: " << response.error_message;
2167}
2168
2169TEST(tombstoned, intercept_bad_pid) {
2170 const pid_t fake_pid = -1;
2171 unique_fd intercept_fd, output_fd;
2172 InterceptResponse response = {};
2173 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdNativeBacktrace);
2174 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2175 << "Error message: " << response.error_message;
2176 ASSERT_MATCH(response.error_message, "bad pid");
2177}
2178
2179TEST(tombstoned, intercept_bad_dump_types) {
2180 const pid_t fake_pid = 1'234'567;
2181 unique_fd intercept_fd, output_fd;
2182 InterceptResponse response = {};
2183 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response,
2184 static_cast<DebuggerdDumpType>(20));
2185 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2186 << "Error message: " << response.error_message;
2187 ASSERT_MATCH(response.error_message, "bad dump type \\[unknown\\]");
2188
2189 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdAnyIntercept);
2190 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2191 << "Error message: " << response.error_message;
2192 ASSERT_MATCH(response.error_message, "bad dump type kDebuggerdAnyIntercept");
2193
2194 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstoneProto);
2195 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2196 << "Error message: " << response.error_message;
2197 ASSERT_MATCH(response.error_message, "bad dump type kDebuggerdTombstoneProto");
2198}
2199
2200TEST(tombstoned, intercept_already_registered) {
2201 const pid_t fake_pid = 1'234'567;
2202 unique_fd intercept_fd1, output_fd1;
2203 InterceptResponse response = {};
2204 tombstoned_intercept(fake_pid, &intercept_fd1, &output_fd1, &response, kDebuggerdTombstone);
2205 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2206 << "Error message: " << response.error_message;
2207
2208 unique_fd intercept_fd2, output_fd2;
2209 tombstoned_intercept(fake_pid, &intercept_fd2, &output_fd2, &response, kDebuggerdTombstone);
2210 ASSERT_EQ(InterceptStatus::kFailedAlreadyRegistered, response.status)
2211 << "Error message: " << response.error_message;
2212 ASSERT_MATCH(response.error_message, "already registered, type kDebuggerdTombstone");
2213}
2214
2215TEST(tombstoned, intercept_tombstone_proto_matched_to_tombstone) {
2216 const pid_t fake_pid = 1'234'567;
2217
2218 unique_fd intercept_fd, output_fd;
2219 InterceptResponse response = {};
2220 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2221 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2222 << "Error message: " << response.error_message;
2223
2224 const char data[] = "tombstone_proto";
2225 unique_fd tombstoned_socket, input_fd;
2226 ASSERT_TRUE(
2227 tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdTombstoneProto));
2228 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), data, sizeof(data)));
2229 tombstoned_notify_completion(tombstoned_socket.get());
2230
2231 char outbuf[sizeof(data)];
2232 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
2233 ASSERT_STREQ("tombstone_proto", outbuf);
Narayan Kamathca5e9082017-06-02 15:42:06 +01002234}
2235
2236TEST(tombstoned, intercept_any) {
2237 const pid_t fake_pid = 1'234'567;
2238
2239 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002240 InterceptResponse response = {};
2241 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdNativeBacktrace);
2242 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2243 << "Error message: " << response.error_message;
Narayan Kamathca5e9082017-06-02 15:42:06 +01002244
2245 const char any[] = "any";
2246 unique_fd tombstoned_socket, input_fd;
2247 ASSERT_TRUE(tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdAnyIntercept));
2248 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), any, sizeof(any)));
2249 tombstoned_notify_completion(tombstoned_socket.get());
2250
2251 char outbuf[sizeof(any)];
2252 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
2253 ASSERT_STREQ("any", outbuf);
2254}
Josh Gao2b22ae12018-09-12 14:51:03 -07002255
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002256TEST(tombstoned, intercept_any_failed_with_multiple_intercepts) {
2257 const pid_t fake_pid = 1'234'567;
2258
2259 InterceptResponse response = {};
2260 unique_fd intercept_fd1, output_fd1;
2261 tombstoned_intercept(fake_pid, &intercept_fd1, &output_fd1, &response, kDebuggerdNativeBacktrace);
2262 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2263 << "Error message: " << response.error_message;
2264
2265 unique_fd intercept_fd2, output_fd2;
2266 tombstoned_intercept(fake_pid, &intercept_fd2, &output_fd2, &response, kDebuggerdJavaBacktrace);
2267 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2268 << "Error message: " << response.error_message;
2269
2270 unique_fd tombstoned_socket, input_fd;
2271 ASSERT_FALSE(tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdAnyIntercept));
2272}
2273
2274TEST(tombstoned, intercept_multiple_verify_intercept) {
2275 // Need to use our pid for java since that will verify the pid.
2276 const pid_t fake_pid = getpid();
2277
2278 InterceptResponse response = {};
2279 unique_fd intercept_fd1, output_fd1;
2280 tombstoned_intercept(fake_pid, &intercept_fd1, &output_fd1, &response, kDebuggerdNativeBacktrace);
2281 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2282 << "Error message: " << response.error_message;
2283
2284 unique_fd intercept_fd2, output_fd2;
2285 tombstoned_intercept(fake_pid, &intercept_fd2, &output_fd2, &response, kDebuggerdJavaBacktrace);
2286 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2287 << "Error message: " << response.error_message;
2288
2289 unique_fd intercept_fd3, output_fd3;
2290 tombstoned_intercept(fake_pid, &intercept_fd3, &output_fd3, &response, kDebuggerdTombstone);
2291 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2292 << "Error message: " << response.error_message;
2293
2294 const char native_data[] = "native";
2295 unique_fd tombstoned_socket1, input_fd1;
2296 ASSERT_TRUE(
2297 tombstoned_connect(fake_pid, &tombstoned_socket1, &input_fd1, kDebuggerdNativeBacktrace));
2298 ASSERT_TRUE(android::base::WriteFully(input_fd1.get(), native_data, sizeof(native_data)));
2299 tombstoned_notify_completion(tombstoned_socket1.get());
2300
2301 char native_outbuf[sizeof(native_data)];
2302 ASSERT_TRUE(android::base::ReadFully(output_fd1.get(), native_outbuf, sizeof(native_outbuf)));
2303 ASSERT_STREQ("native", native_outbuf);
2304
2305 const char java_data[] = "java";
2306 unique_fd tombstoned_socket2, input_fd2;
2307 ASSERT_TRUE(
2308 tombstoned_connect(fake_pid, &tombstoned_socket2, &input_fd2, kDebuggerdJavaBacktrace));
2309 ASSERT_TRUE(android::base::WriteFully(input_fd2.get(), java_data, sizeof(java_data)));
2310 tombstoned_notify_completion(tombstoned_socket2.get());
2311
2312 char java_outbuf[sizeof(java_data)];
2313 ASSERT_TRUE(android::base::ReadFully(output_fd2.get(), java_outbuf, sizeof(java_outbuf)));
2314 ASSERT_STREQ("java", java_outbuf);
2315
2316 const char tomb_data[] = "tombstone";
2317 unique_fd tombstoned_socket3, input_fd3;
2318 ASSERT_TRUE(tombstoned_connect(fake_pid, &tombstoned_socket3, &input_fd3, kDebuggerdTombstone));
2319 ASSERT_TRUE(android::base::WriteFully(input_fd3.get(), tomb_data, sizeof(tomb_data)));
2320 tombstoned_notify_completion(tombstoned_socket3.get());
2321
2322 char tomb_outbuf[sizeof(tomb_data)];
2323 ASSERT_TRUE(android::base::ReadFully(output_fd3.get(), tomb_outbuf, sizeof(tomb_outbuf)));
2324 ASSERT_STREQ("tombstone", tomb_outbuf);
2325}
2326
Josh Gao2b22ae12018-09-12 14:51:03 -07002327TEST(tombstoned, interceptless_backtrace) {
2328 // Generate 50 backtraces, and then check to see that we haven't created 50 new tombstones.
2329 auto get_tombstone_timestamps = []() -> std::map<int, time_t> {
2330 std::map<int, time_t> result;
2331 for (int i = 0; i < 99; ++i) {
2332 std::string path = android::base::StringPrintf("/data/tombstones/tombstone_%02d", i);
2333 struct stat st;
2334 if (stat(path.c_str(), &st) == 0) {
2335 result[i] = st.st_mtim.tv_sec;
2336 }
2337 }
2338 return result;
2339 };
2340
2341 auto before = get_tombstone_timestamps();
2342 for (int i = 0; i < 50; ++i) {
2343 raise_debugger_signal(kDebuggerdNativeBacktrace);
2344 }
2345 auto after = get_tombstone_timestamps();
2346
2347 int diff = 0;
2348 for (int i = 0; i < 99; ++i) {
2349 if (after.count(i) == 0) {
2350 continue;
2351 }
2352 if (before.count(i) == 0) {
2353 ++diff;
2354 continue;
2355 }
2356 if (before[i] != after[i]) {
2357 ++diff;
2358 }
2359 }
2360
2361 // We can't be sure that nothing's crash looping in the background.
2362 // This should be good enough, though...
2363 ASSERT_LT(diff, 10) << "too many new tombstones; is something crashing in the background?";
2364}
Christopher Ferris481e8372019-07-15 17:13:24 -07002365
2366static __attribute__((__noinline__)) void overflow_stack(void* p) {
2367 void* buf[1];
2368 buf[0] = p;
2369 static volatile void* global = buf;
2370 if (global) {
2371 global = buf;
2372 overflow_stack(&buf);
2373 }
2374}
2375
2376TEST_F(CrasherTest, stack_overflow) {
2377 int intercept_result;
2378 unique_fd output_fd;
2379 StartProcess([]() { overflow_stack(nullptr); });
2380
2381 StartIntercept(&output_fd);
2382 FinishCrasher();
2383 AssertDeath(SIGSEGV);
2384 FinishIntercept(&intercept_result);
2385
2386 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2387
2388 std::string result;
2389 ConsumeFd(std::move(output_fd), &result);
2390 ASSERT_MATCH(result, R"(Cause: stack pointer[^\n]*stack overflow.\n)");
2391}
Josh Gao76e1e302021-01-26 15:53:11 -08002392
Christopher Ferris22035cc2023-01-31 17:50:22 -08002393static std::string GetTestLibraryPath() {
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002394 std::string test_lib(testing::internal::GetArgvs()[0]);
2395 auto const value = test_lib.find_last_of('/');
2396 if (value == std::string::npos) {
2397 test_lib = "./";
2398 } else {
2399 test_lib = test_lib.substr(0, value + 1) + "./";
2400 }
Christopher Ferris22035cc2023-01-31 17:50:22 -08002401 return test_lib + "libcrash_test.so";
2402}
2403
2404static void CreateEmbeddedLibrary(int out_fd) {
2405 std::string test_lib(GetTestLibraryPath());
2406 android::base::unique_fd fd(open(test_lib.c_str(), O_RDONLY | O_CLOEXEC));
2407 ASSERT_NE(fd.get(), -1);
2408 off_t file_size = lseek(fd, 0, SEEK_END);
2409 ASSERT_EQ(lseek(fd, 0, SEEK_SET), 0);
2410 std::vector<uint8_t> contents(file_size);
2411 ASSERT_TRUE(android::base::ReadFully(fd, contents.data(), contents.size()));
2412
2413 // Put the shared library data at a pagesize() offset.
2414 ASSERT_EQ(lseek(out_fd, 4 * getpagesize(), SEEK_CUR), 4 * getpagesize());
2415 ASSERT_EQ(static_cast<size_t>(write(out_fd, contents.data(), contents.size())), contents.size());
2416}
2417
2418TEST_F(CrasherTest, non_zero_offset_in_library) {
2419 int intercept_result;
2420 unique_fd output_fd;
2421 TemporaryFile tf;
2422 CreateEmbeddedLibrary(tf.fd);
2423 StartProcess([&tf]() {
2424 android_dlextinfo extinfo{};
2425 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
2426 extinfo.library_fd = tf.fd;
2427 extinfo.library_fd_offset = 4 * getpagesize();
2428 void* handle = android_dlopen_ext(tf.path, RTLD_NOW, &extinfo);
2429 if (handle == nullptr) {
2430 _exit(1);
2431 }
2432 void (*crash_func)() = reinterpret_cast<void (*)()>(dlsym(handle, "crash"));
2433 if (crash_func == nullptr) {
2434 _exit(1);
2435 }
2436 crash_func();
2437 });
2438
2439 StartIntercept(&output_fd);
2440 FinishCrasher();
2441 AssertDeath(SIGSEGV);
2442 FinishIntercept(&intercept_result);
2443
2444 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2445
2446 std::string result;
2447 ConsumeFd(std::move(output_fd), &result);
2448
2449 // Verify the crash includes an offset value in the backtrace.
2450 std::string match_str = android::base::StringPrintf("%s\\!libcrash_test.so \\(offset 0x%x\\)",
2451 tf.path, 4 * getpagesize());
2452 ASSERT_MATCH(result, match_str);
2453}
2454
2455static bool CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) {
2456 std::string test_lib(GetTestLibraryPath());
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002457
2458 *tmp_so_name = std::string(tmp_dir) + "/libcrash_test.so";
2459 std::string cp_cmd = android::base::StringPrintf("cp %s %s", test_lib.c_str(), tmp_dir);
2460
2461 // Copy the shared so to a tempory directory.
2462 return system(cp_cmd.c_str()) == 0;
2463}
2464
2465TEST_F(CrasherTest, unreadable_elf) {
2466 int intercept_result;
2467 unique_fd output_fd;
Christopher Ferrisc95047d2022-03-14 15:02:11 -07002468 std::string tmp_so_name;
2469 StartProcess([&tmp_so_name]() {
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002470 TemporaryDir td;
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002471 if (!CopySharedLibrary(td.path, &tmp_so_name)) {
2472 _exit(1);
2473 }
2474 void* handle = dlopen(tmp_so_name.c_str(), RTLD_NOW);
2475 if (handle == nullptr) {
2476 _exit(1);
2477 }
2478 // Delete the original shared library so that we get the warning
2479 // about unreadable elf files.
2480 if (unlink(tmp_so_name.c_str()) == -1) {
2481 _exit(1);
2482 }
2483 void (*crash_func)() = reinterpret_cast<void (*)()>(dlsym(handle, "crash"));
2484 if (crash_func == nullptr) {
2485 _exit(1);
2486 }
2487 crash_func();
2488 });
2489
2490 StartIntercept(&output_fd);
2491 FinishCrasher();
2492 AssertDeath(SIGSEGV);
2493 FinishIntercept(&intercept_result);
2494
2495 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2496
2497 std::string result;
2498 ConsumeFd(std::move(output_fd), &result);
2499 ASSERT_MATCH(result, R"(NOTE: Function names and BuildId information is missing )");
Christopher Ferrisc95047d2022-03-14 15:02:11 -07002500 std::string match_str = "NOTE: " + tmp_so_name;
2501 ASSERT_MATCH(result, match_str);
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002502}
2503
Christopher Ferris20f50ec2024-01-03 02:30:03 +00002504void CheckForTombstone(const struct stat& text_st, std::optional<std::string>& tombstone_file) {
2505 static std::regex tombstone_re("tombstone_\\d+");
Christopher Ferris35da2882021-02-17 15:39:06 -08002506 std::unique_ptr<DIR, decltype(&closedir)> dir_h(opendir("/data/tombstones"), closedir);
2507 ASSERT_TRUE(dir_h != nullptr);
Christopher Ferris35da2882021-02-17 15:39:06 -08002508 dirent* entry;
2509 while ((entry = readdir(dir_h.get())) != nullptr) {
2510 if (!std::regex_match(entry->d_name, tombstone_re)) {
2511 continue;
2512 }
2513 std::string path = android::base::StringPrintf("/data/tombstones/%s", entry->d_name);
Josh Gao76e1e302021-01-26 15:53:11 -08002514
2515 struct stat st;
2516 if (TEMP_FAILURE_RETRY(stat(path.c_str(), &st)) != 0) {
2517 continue;
2518 }
2519
2520 if (st.st_dev == text_st.st_dev && st.st_ino == text_st.st_ino) {
Christopher Ferris35da2882021-02-17 15:39:06 -08002521 tombstone_file = path;
Josh Gao76e1e302021-01-26 15:53:11 -08002522 break;
2523 }
2524 }
Christopher Ferris20f50ec2024-01-03 02:30:03 +00002525}
Josh Gao76e1e302021-01-26 15:53:11 -08002526
Christopher Ferris20f50ec2024-01-03 02:30:03 +00002527TEST(tombstoned, proto) {
2528 const pid_t self = getpid();
2529 unique_fd tombstoned_socket, text_fd, proto_fd;
2530 ASSERT_TRUE(
2531 tombstoned_connect(self, &tombstoned_socket, &text_fd, &proto_fd, kDebuggerdTombstoneProto));
2532
2533 tombstoned_notify_completion(tombstoned_socket.get());
2534
2535 ASSERT_NE(-1, text_fd.get());
2536 ASSERT_NE(-1, proto_fd.get());
2537
2538 struct stat text_st;
2539 ASSERT_EQ(0, fstat(text_fd.get(), &text_st));
2540
2541 std::optional<std::string> tombstone_file;
2542 // Allow up to 5 seconds for the tombstone to be written to the system.
2543 const auto max_wait_time = std::chrono::seconds(5) * android::base::HwTimeoutMultiplier();
2544 const auto start = std::chrono::high_resolution_clock::now();
2545 while (true) {
2546 std::this_thread::sleep_for(100ms);
2547 CheckForTombstone(text_st, tombstone_file);
2548 if (tombstone_file) {
2549 break;
2550 }
2551 if (std::chrono::high_resolution_clock::now() - start > max_wait_time) {
2552 break;
2553 }
2554 }
2555
2556 ASSERT_TRUE(tombstone_file) << "Timed out trying to find tombstone file.";
Christopher Ferris35da2882021-02-17 15:39:06 -08002557 std::string proto_path = tombstone_file.value() + ".pb";
Josh Gao76e1e302021-01-26 15:53:11 -08002558
2559 struct stat proto_fd_st;
2560 struct stat proto_file_st;
2561 ASSERT_EQ(0, fstat(proto_fd.get(), &proto_fd_st));
2562 ASSERT_EQ(0, stat(proto_path.c_str(), &proto_file_st));
2563
2564 ASSERT_EQ(proto_fd_st.st_dev, proto_file_st.st_dev);
2565 ASSERT_EQ(proto_fd_st.st_ino, proto_file_st.st_ino);
2566}
2567
2568TEST(tombstoned, proto_intercept) {
2569 const pid_t self = getpid();
2570 unique_fd intercept_fd, output_fd;
Josh Gao76e1e302021-01-26 15:53:11 -08002571
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002572 InterceptResponse response = {};
2573 tombstoned_intercept(self, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2574 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2575 << "Error message: " << response.error_message;
Josh Gao76e1e302021-01-26 15:53:11 -08002576
2577 unique_fd tombstoned_socket, text_fd, proto_fd;
2578 ASSERT_TRUE(
2579 tombstoned_connect(self, &tombstoned_socket, &text_fd, &proto_fd, kDebuggerdTombstoneProto));
2580 ASSERT_TRUE(android::base::WriteStringToFd("foo", text_fd.get()));
2581 tombstoned_notify_completion(tombstoned_socket.get());
2582
2583 text_fd.reset();
2584
2585 std::string output;
2586 ASSERT_TRUE(android::base::ReadFdToString(output_fd, &output));
2587 ASSERT_EQ("foo", output);
2588}
Christopher Ferrisa3e9a0b2021-07-29 12:38:07 -07002589
2590// Verify that when an intercept is present for the main thread, and the signal
2591// is received on a different thread, the intercept still works.
2592TEST_F(CrasherTest, intercept_for_main_thread_signal_on_side_thread) {
2593 StartProcess([]() {
2594 std::thread thread([]() {
2595 // Raise the signal on the side thread.
2596 raise_debugger_signal(kDebuggerdNativeBacktrace);
2597 });
2598 thread.join();
2599 _exit(0);
2600 });
2601
2602 unique_fd output_fd;
2603 StartIntercept(&output_fd, kDebuggerdNativeBacktrace);
2604 FinishCrasher();
2605 AssertDeath(0);
2606
2607 int intercept_result;
2608 FinishIntercept(&intercept_result);
2609 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2610
2611 std::string result;
2612 ConsumeFd(std::move(output_fd), &result);
2613 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
2614}
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002615
2616static std::string format_pointer(uintptr_t ptr) {
2617#if defined(__LP64__)
2618 return android::base::StringPrintf("%08x'%08x", static_cast<uint32_t>(ptr >> 32),
2619 static_cast<uint32_t>(ptr & 0xffffffff));
2620#else
2621 return android::base::StringPrintf("%08x", static_cast<uint32_t>(ptr & 0xffffffff));
2622#endif
2623}
2624
2625static std::string format_pointer(void* ptr) {
2626 return format_pointer(reinterpret_cast<uintptr_t>(ptr));
2627}
2628
2629static std::string format_full_pointer(uintptr_t ptr) {
2630#if defined(__LP64__)
2631 return android::base::StringPrintf("%016" PRIx64, ptr);
2632#else
2633 return android::base::StringPrintf("%08x", ptr);
2634#endif
2635}
2636
2637static std::string format_full_pointer(void* ptr) {
2638 return format_full_pointer(reinterpret_cast<uintptr_t>(ptr));
2639}
2640
2641__attribute__((__noinline__)) int crash_call(uintptr_t ptr) {
2642 int* crash_ptr = reinterpret_cast<int*>(ptr);
2643 *crash_ptr = 1;
2644 return *crash_ptr;
2645}
2646
2647// Verify that a fault address before the first map is properly handled.
2648TEST_F(CrasherTest, fault_address_before_first_map) {
2649 StartProcess([]() {
2650 ASSERT_EQ(0, crash_call(0x1024));
2651 _exit(0);
2652 });
2653
2654 unique_fd output_fd;
2655 StartIntercept(&output_fd);
2656 FinishCrasher();
2657 AssertDeath(SIGSEGV);
2658
2659 int intercept_result;
2660 FinishIntercept(&intercept_result);
2661 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2662
2663 std::string result;
2664 ConsumeFd(std::move(output_fd), &result);
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002665 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+1024)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002666
2667 ASSERT_MATCH(result, R"(\nmemory map \(.*\):\n)");
2668
2669 std::string match_str = android::base::StringPrintf(
2670 R"(memory map .*:\n--->Fault address falls at %s before any mapped regions\n )",
2671 format_pointer(0x1024).c_str());
2672 ASSERT_MATCH(result, match_str);
2673}
2674
2675// Verify that a fault address after the last map is properly handled.
2676TEST_F(CrasherTest, fault_address_after_last_map) {
Florian Mayerb4979292022-04-15 14:35:17 -07002677 // This makes assumptions about the memory layout that are not true in HWASan
2678 // processes.
2679 SKIP_WITH_HWASAN;
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002680 uintptr_t crash_uptr = untag_address(UINTPTR_MAX - 15);
2681 StartProcess([crash_uptr]() {
2682 ASSERT_EQ(0, crash_call(crash_uptr));
2683 _exit(0);
2684 });
2685
2686 unique_fd output_fd;
2687 StartIntercept(&output_fd);
2688 FinishCrasher();
2689 AssertDeath(SIGSEGV);
2690
2691 int intercept_result;
2692 FinishIntercept(&intercept_result);
2693 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2694
2695 std::string result;
2696 ConsumeFd(std::move(output_fd), &result);
2697
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002698 std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x)";
2699 match_str += format_full_pointer(crash_uptr);
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002700 ASSERT_MATCH(result, match_str);
2701
Ryan Prichardbc227032024-02-29 14:40:57 -08002702 ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002703
Christopher Ferris3a0833c2023-07-28 13:07:53 -07002704 // Verifies that the fault address error message is at the end of the
2705 // maps section. To do this, the check below looks for the start of the
2706 // open files section or the start of the log file section. It's possible
2707 // for either of these sections to be present after the maps section right
2708 // now.
2709 // If the sections move around, this check might need to be modified.
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002710 match_str = android::base::StringPrintf(
Christopher Ferris3a0833c2023-07-28 13:07:53 -07002711 R"(\n--->Fault address falls at %s after any mapped regions\n(---------|\nopen files:))",
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002712 format_pointer(crash_uptr).c_str());
2713 ASSERT_MATCH(result, match_str);
2714}
2715
2716// Verify that a fault address between maps is properly handled.
2717TEST_F(CrasherTest, fault_address_between_maps) {
2718 // Create a map before the fork so it will be present in the child.
2719 void* start_ptr =
2720 mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2721 ASSERT_NE(MAP_FAILED, start_ptr);
2722 // Unmap the page in the middle.
2723 void* middle_ptr =
2724 reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start_ptr) + getpagesize());
2725 ASSERT_EQ(0, munmap(middle_ptr, getpagesize()));
2726
2727 StartProcess([middle_ptr]() {
2728 ASSERT_EQ(0, crash_call(reinterpret_cast<uintptr_t>(middle_ptr)));
2729 _exit(0);
2730 });
2731
2732 // Unmap the two maps.
2733 ASSERT_EQ(0, munmap(start_ptr, getpagesize()));
2734 void* end_ptr =
2735 reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start_ptr) + 2 * getpagesize());
2736 ASSERT_EQ(0, munmap(end_ptr, getpagesize()));
2737
2738 unique_fd output_fd;
2739 StartIntercept(&output_fd);
2740 FinishCrasher();
2741 AssertDeath(SIGSEGV);
2742
2743 int intercept_result;
2744 FinishIntercept(&intercept_result);
2745 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2746
2747 std::string result;
2748 ConsumeFd(std::move(output_fd), &result);
2749
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002750 std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x)";
2751 match_str += format_full_pointer(reinterpret_cast<uintptr_t>(middle_ptr));
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002752 ASSERT_MATCH(result, match_str);
2753
Ryan Prichardbc227032024-02-29 14:40:57 -08002754 ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002755
2756 match_str = android::base::StringPrintf(
2757 R"( %s.*\n--->Fault address falls at %s between mapped regions\n %s)",
2758 format_pointer(start_ptr).c_str(), format_pointer(middle_ptr).c_str(),
2759 format_pointer(end_ptr).c_str());
2760 ASSERT_MATCH(result, match_str);
2761}
2762
2763// Verify that a fault address happens in the correct map.
2764TEST_F(CrasherTest, fault_address_in_map) {
2765 // Create a map before the fork so it will be present in the child.
2766 void* ptr = mmap(nullptr, getpagesize(), 0, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2767 ASSERT_NE(MAP_FAILED, ptr);
2768
2769 StartProcess([ptr]() {
2770 ASSERT_EQ(0, crash_call(reinterpret_cast<uintptr_t>(ptr)));
2771 _exit(0);
2772 });
2773
2774 ASSERT_EQ(0, munmap(ptr, getpagesize()));
2775
2776 unique_fd output_fd;
2777 StartIntercept(&output_fd);
2778 FinishCrasher();
2779 AssertDeath(SIGSEGV);
2780
2781 int intercept_result;
2782 FinishIntercept(&intercept_result);
2783 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2784
2785 std::string result;
2786 ConsumeFd(std::move(output_fd), &result);
2787
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002788 std::string match_str = R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\), fault addr 0x)";
2789 match_str += format_full_pointer(reinterpret_cast<uintptr_t>(ptr));
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002790 ASSERT_MATCH(result, match_str);
2791
Ryan Prichardbc227032024-02-29 14:40:57 -08002792 ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002793
2794 match_str = android::base::StringPrintf(R"(\n--->%s.*\n)", format_pointer(ptr).c_str());
2795 ASSERT_MATCH(result, match_str);
2796}
Christopher Ferris2038cc72021-09-15 03:57:10 +00002797
2798static constexpr uint32_t kDexData[] = {
2799 0x0a786564, 0x00383330, 0xc98b3ab8, 0xf3749d94, 0xaecca4d8, 0xffc7b09a, 0xdca9ca7f, 0x5be5deab,
2800 0x00000220, 0x00000070, 0x12345678, 0x00000000, 0x00000000, 0x0000018c, 0x00000008, 0x00000070,
2801 0x00000004, 0x00000090, 0x00000002, 0x000000a0, 0x00000000, 0x00000000, 0x00000003, 0x000000b8,
2802 0x00000001, 0x000000d0, 0x00000130, 0x000000f0, 0x00000122, 0x0000012a, 0x00000132, 0x00000146,
2803 0x00000151, 0x00000154, 0x00000158, 0x0000016d, 0x00000001, 0x00000002, 0x00000004, 0x00000006,
2804 0x00000004, 0x00000002, 0x00000000, 0x00000005, 0x00000002, 0x0000011c, 0x00000000, 0x00000000,
2805 0x00010000, 0x00000007, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000,
2806 0x00000003, 0x00000000, 0x0000017e, 0x00000000, 0x00010001, 0x00000001, 0x00000173, 0x00000004,
2807 0x00021070, 0x000e0000, 0x00010001, 0x00000000, 0x00000178, 0x00000001, 0x0000000e, 0x00000001,
2808 0x3c060003, 0x74696e69, 0x4c06003e, 0x6e69614d, 0x4c12003b, 0x6176616a, 0x6e616c2f, 0x624f2f67,
2809 0x7463656a, 0x4d09003b, 0x2e6e6961, 0x6176616a, 0x00560100, 0x004c5602, 0x6a4c5b13, 0x2f617661,
2810 0x676e616c, 0x7274532f, 0x3b676e69, 0x616d0400, 0x01006e69, 0x000e0700, 0x07000103, 0x0000000e,
2811 0x81000002, 0x01f00480, 0x02880901, 0x0000000c, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
2812 0x00000008, 0x00000070, 0x00000002, 0x00000004, 0x00000090, 0x00000003, 0x00000002, 0x000000a0,
2813 0x00000005, 0x00000003, 0x000000b8, 0x00000006, 0x00000001, 0x000000d0, 0x00002001, 0x00000002,
2814 0x000000f0, 0x00001001, 0x00000001, 0x0000011c, 0x00002002, 0x00000008, 0x00000122, 0x00002003,
2815 0x00000002, 0x00000173, 0x00002000, 0x00000001, 0x0000017e, 0x00001000, 0x00000001, 0x0000018c,
2816};
2817
2818TEST_F(CrasherTest, verify_dex_pc_with_function_name) {
2819 StartProcess([]() {
2820 TemporaryDir td;
2821 std::string tmp_so_name;
2822 if (!CopySharedLibrary(td.path, &tmp_so_name)) {
2823 _exit(1);
2824 }
2825
2826 // In order to cause libunwindstack to look for this __dex_debug_descriptor
2827 // move the library to which has a basename of libart.so.
2828 std::string art_so_name = android::base::Dirname(tmp_so_name) + "/libart.so";
2829 ASSERT_EQ(0, rename(tmp_so_name.c_str(), art_so_name.c_str()));
2830 void* handle = dlopen(art_so_name.c_str(), RTLD_NOW | RTLD_LOCAL);
2831 if (handle == nullptr) {
2832 _exit(1);
2833 }
2834
2835 void* ptr =
2836 mmap(nullptr, sizeof(kDexData), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2837 ASSERT_TRUE(ptr != MAP_FAILED);
2838 memcpy(ptr, kDexData, sizeof(kDexData));
2839 prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, sizeof(kDexData), "dex");
2840
2841 JITCodeEntry dex_entry = {.symfile_addr = reinterpret_cast<uintptr_t>(ptr),
2842 .symfile_size = sizeof(kDexData)};
2843
2844 JITDescriptor* dex_debug =
2845 reinterpret_cast<JITDescriptor*>(dlsym(handle, "__dex_debug_descriptor"));
2846 ASSERT_TRUE(dex_debug != nullptr);
2847 dex_debug->version = 1;
2848 dex_debug->action_flag = 0;
2849 dex_debug->relevant_entry = 0;
2850 dex_debug->first_entry = reinterpret_cast<uintptr_t>(&dex_entry);
2851
2852 // This sets the magic dex pc value for register 0, using the value
2853 // of register 1 + 0x102.
2854 asm(".cfi_escape "
2855 "0x16 /* DW_CFA_val_expression */, 0, 0x0a /* size */,"
2856 "0x0c /* DW_OP_const4u */, 0x44, 0x45, 0x58, 0x31, /* magic = 'DEX1' */"
2857 "0x13 /* DW_OP_drop */,"
2858 "0x92 /* DW_OP_bregx */, 1, 0x82, 0x02 /* 2-byte SLEB128 */");
2859
2860 // For each different architecture, set register one to the dex ptr mmap
2861 // created above. Then do a nullptr dereference to force a crash.
2862#if defined(__arm__)
2863 asm volatile(
2864 "mov r1, %[base]\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002865 "mov r2, #0\n"
2866 "str r2, [r2]\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002867 : [base] "+r"(ptr)
2868 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002869 : "r1", "r2", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002870#elif defined(__aarch64__)
2871 asm volatile(
2872 "mov x1, %[base]\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002873 "mov x2, #0\n"
2874 "str xzr, [x2]\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002875 : [base] "+r"(ptr)
2876 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002877 : "x1", "x2", "memory");
2878#elif defined(__riscv)
2879 // TODO: x1 is ra (the link register) on riscv64, so this might have
2880 // unintended consequences, but we'll need to change the .cfi_escape if so.
2881 asm volatile(
2882 "mv x1, %[base]\n"
2883 "sw zero, 0(zero)\n"
2884 : [base] "+r"(ptr)
2885 :
2886 : "x1", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002887#elif defined(__i386__)
2888 asm volatile(
2889 "mov %[base], %%ecx\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002890 "movl $0, 0\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002891 : [base] "+r"(ptr)
2892 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002893 : "ecx", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002894#elif defined(__x86_64__)
2895 asm volatile(
2896 "mov %[base], %%rdx\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002897 "movq $0, 0\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002898 : [base] "+r"(ptr)
2899 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002900 : "rdx", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002901#else
2902#error "Unsupported architecture"
2903#endif
2904 _exit(0);
2905 });
2906
2907 unique_fd output_fd;
2908 StartIntercept(&output_fd);
2909 FinishCrasher();
2910 AssertDeath(SIGSEGV);
2911
2912 int intercept_result;
2913 FinishIntercept(&intercept_result);
2914 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2915
2916 std::string result;
2917 ConsumeFd(std::move(output_fd), &result);
2918
2919 // Verify the process crashed properly.
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002920 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0*)");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002921
2922 // Now verify that the dex_pc frame includes a proper function name.
2923 ASSERT_MATCH(result, R"( \[anon:dex\] \(Main\.\<init\>\+2)");
2924}
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00002925
2926static std::string format_map_pointer(uintptr_t ptr) {
2927#if defined(__LP64__)
2928 return android::base::StringPrintf("%08x'%08x", static_cast<uint32_t>(ptr >> 32),
2929 static_cast<uint32_t>(ptr & 0xffffffff));
2930#else
2931 return android::base::StringPrintf("%08x", ptr);
2932#endif
2933}
2934
2935// Verify that map data is properly formatted.
2936TEST_F(CrasherTest, verify_map_format) {
2937 // Create multiple maps to make sure that the map data is formatted properly.
2938 void* none_map = mmap(nullptr, getpagesize(), 0, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2939 ASSERT_NE(MAP_FAILED, none_map);
2940 void* r_map = mmap(nullptr, getpagesize(), PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2941 ASSERT_NE(MAP_FAILED, r_map);
2942 void* w_map = mmap(nullptr, getpagesize(), PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2943 ASSERT_NE(MAP_FAILED, w_map);
2944 void* x_map = mmap(nullptr, getpagesize(), PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2945 ASSERT_NE(MAP_FAILED, x_map);
2946
2947 TemporaryFile tf;
2948 ASSERT_EQ(0x2000, lseek(tf.fd, 0x2000, SEEK_SET));
2949 char c = 'f';
2950 ASSERT_EQ(1, write(tf.fd, &c, 1));
2951 ASSERT_EQ(0x5000, lseek(tf.fd, 0x5000, SEEK_SET));
2952 ASSERT_EQ(1, write(tf.fd, &c, 1));
2953 ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
2954 void* file_map = mmap(nullptr, 0x3001, PROT_READ, MAP_PRIVATE, tf.fd, 0x2000);
2955 ASSERT_NE(MAP_FAILED, file_map);
2956
2957 StartProcess([]() { abort(); });
2958
2959 ASSERT_EQ(0, munmap(none_map, getpagesize()));
2960 ASSERT_EQ(0, munmap(r_map, getpagesize()));
2961 ASSERT_EQ(0, munmap(w_map, getpagesize()));
2962 ASSERT_EQ(0, munmap(x_map, getpagesize()));
2963 ASSERT_EQ(0, munmap(file_map, 0x3001));
2964
2965 unique_fd output_fd;
2966 StartIntercept(&output_fd);
2967 FinishCrasher();
2968 AssertDeath(SIGABRT);
2969 int intercept_result;
2970 FinishIntercept(&intercept_result);
2971
2972 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2973
2974 std::string result;
2975 ConsumeFd(std::move(output_fd), &result);
2976
2977 std::string match_str;
2978 // Verify none.
2979 match_str = android::base::StringPrintf(
2980 " %s-%s --- 0 1000\\n",
2981 format_map_pointer(reinterpret_cast<uintptr_t>(none_map)).c_str(),
2982 format_map_pointer(reinterpret_cast<uintptr_t>(none_map) + getpagesize() - 1).c_str());
2983 ASSERT_MATCH(result, match_str);
2984
2985 // Verify read-only.
2986 match_str = android::base::StringPrintf(
2987 " %s-%s r-- 0 1000\\n",
2988 format_map_pointer(reinterpret_cast<uintptr_t>(r_map)).c_str(),
2989 format_map_pointer(reinterpret_cast<uintptr_t>(r_map) + getpagesize() - 1).c_str());
2990 ASSERT_MATCH(result, match_str);
2991
2992 // Verify write-only.
2993 match_str = android::base::StringPrintf(
2994 " %s-%s -w- 0 1000\\n",
2995 format_map_pointer(reinterpret_cast<uintptr_t>(w_map)).c_str(),
2996 format_map_pointer(reinterpret_cast<uintptr_t>(w_map) + getpagesize() - 1).c_str());
2997 ASSERT_MATCH(result, match_str);
2998
2999 // Verify exec-only.
3000 match_str = android::base::StringPrintf(
3001 " %s-%s --x 0 1000\\n",
3002 format_map_pointer(reinterpret_cast<uintptr_t>(x_map)).c_str(),
3003 format_map_pointer(reinterpret_cast<uintptr_t>(x_map) + getpagesize() - 1).c_str());
3004 ASSERT_MATCH(result, match_str);
3005
3006 // Verify file map with non-zero offset and a name.
3007 match_str = android::base::StringPrintf(
3008 " %s-%s r-- 2000 4000 %s\\n",
3009 format_map_pointer(reinterpret_cast<uintptr_t>(file_map)).c_str(),
3010 format_map_pointer(reinterpret_cast<uintptr_t>(file_map) + 0x3fff).c_str(), tf.path);
3011 ASSERT_MATCH(result, match_str);
3012}
3013
3014// Verify that the tombstone map data is correct.
3015TEST_F(CrasherTest, verify_header) {
3016 StartProcess([]() { abort(); });
3017
3018 unique_fd output_fd;
3019 StartIntercept(&output_fd);
3020 FinishCrasher();
3021 AssertDeath(SIGABRT);
3022 int intercept_result;
3023 FinishIntercept(&intercept_result);
3024
3025 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3026
3027 std::string result;
3028 ConsumeFd(std::move(output_fd), &result);
3029
3030 std::string match_str = android::base::StringPrintf(
3031 "Build fingerprint: '%s'\\nRevision: '%s'\\n",
3032 android::base::GetProperty("ro.build.fingerprint", "unknown").c_str(),
3033 android::base::GetProperty("ro.revision", "unknown").c_str());
3034 match_str += android::base::StringPrintf("ABI: '%s'\n", ABI_STRING);
3035 ASSERT_MATCH(result, match_str);
3036}
3037
3038// Verify that the thread header is formatted properly.
3039TEST_F(CrasherTest, verify_thread_header) {
3040 void* shared_map =
3041 mmap(nullptr, sizeof(pid_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
3042 ASSERT_NE(MAP_FAILED, shared_map);
3043 memset(shared_map, 0, sizeof(pid_t));
3044
3045 StartProcess([&shared_map]() {
3046 std::atomic_bool tid_written;
3047 std::thread thread([&tid_written, &shared_map]() {
3048 pid_t tid = gettid();
3049 memcpy(shared_map, &tid, sizeof(pid_t));
3050 tid_written = true;
3051 volatile bool done = false;
3052 while (!done)
3053 ;
3054 });
3055 thread.detach();
3056 while (!tid_written.load(std::memory_order_acquire))
3057 ;
3058 abort();
3059 });
3060
3061 pid_t primary_pid = crasher_pid;
3062
3063 unique_fd output_fd;
3064 StartIntercept(&output_fd);
3065 FinishCrasher();
3066 AssertDeath(SIGABRT);
3067 int intercept_result;
3068 FinishIntercept(&intercept_result);
3069 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3070
3071 // Read the tid data out.
3072 pid_t tid;
3073 memcpy(&tid, shared_map, sizeof(pid_t));
3074 ASSERT_NE(0, tid);
3075
3076 ASSERT_EQ(0, munmap(shared_map, sizeof(pid_t)));
3077
3078 std::string result;
3079 ConsumeFd(std::move(output_fd), &result);
3080
3081 // Verify that there are two headers, one where the tid is "primary_pid"
3082 // and the other where the tid is "tid".
3083 std::string match_str = android::base::StringPrintf("pid: %d, tid: %d, name: .* >>> .* <<<\\n",
3084 primary_pid, primary_pid);
3085 ASSERT_MATCH(result, match_str);
3086
3087 match_str =
3088 android::base::StringPrintf("pid: %d, tid: %d, name: .* >>> .* <<<\\n", primary_pid, tid);
3089 ASSERT_MATCH(result, match_str);
3090}
3091
3092// Verify that there is a BuildID present in the map section and set properly.
3093TEST_F(CrasherTest, verify_build_id) {
3094 StartProcess([]() { abort(); });
3095
3096 unique_fd output_fd;
3097 StartIntercept(&output_fd);
3098 FinishCrasher();
3099 AssertDeath(SIGABRT);
3100 int intercept_result;
3101 FinishIntercept(&intercept_result);
3102 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3103
3104 std::string result;
3105 ConsumeFd(std::move(output_fd), &result);
3106
3107 // Find every /system or /apex lib and verify the BuildID is displayed
3108 // properly.
3109 bool found_valid_elf = false;
3110 std::smatch match;
3111 std::regex build_id_regex(R"( ((/system/|/apex/)\S+) \(BuildId: ([^\)]+)\))");
3112 for (std::string prev_file; std::regex_search(result, match, build_id_regex);
3113 result = match.suffix()) {
3114 if (prev_file == match[1]) {
3115 // Already checked this file.
3116 continue;
3117 }
3118
3119 prev_file = match[1];
Christopher Ferris15038902023-11-10 00:05:49 -08003120 auto elf_memory = unwindstack::Memory::CreateFileMemory(prev_file, 0);
3121 unwindstack::Elf elf(elf_memory);
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00003122 if (!elf.Init() || !elf.valid()) {
3123 // Skipping invalid elf files.
3124 continue;
3125 }
3126 ASSERT_EQ(match[3], elf.GetPrintableBuildID());
3127
3128 found_valid_elf = true;
3129 }
3130 ASSERT_TRUE(found_valid_elf) << "Did not find any elf files with valid BuildIDs to check.";
3131}
Christopher Ferrisbda10642023-04-24 18:14:53 -07003132
3133const char kLogMessage[] = "Should not see this log message.";
3134
3135// Verify that the logd process does not read the log.
3136TEST_F(CrasherTest, logd_skips_reading_logs) {
3137 StartProcess([]() {
3138 pthread_setname_np(pthread_self(), "logd");
3139 LOG(INFO) << kLogMessage;
3140 abort();
3141 });
3142
3143 unique_fd output_fd;
3144 StartIntercept(&output_fd);
3145 FinishCrasher();
3146 AssertDeath(SIGABRT);
3147 int intercept_result;
3148 FinishIntercept(&intercept_result);
3149 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3150
3151 std::string result;
3152 ConsumeFd(std::move(output_fd), &result);
3153 // logd should not contain our log message.
3154 ASSERT_NOT_MATCH(result, kLogMessage);
3155}
3156
3157// Verify that the logd process does not read the log when the non-main
3158// thread crashes.
3159TEST_F(CrasherTest, logd_skips_reading_logs_not_main_thread) {
3160 StartProcess([]() {
3161 pthread_setname_np(pthread_self(), "logd");
3162 LOG(INFO) << kLogMessage;
3163
3164 std::thread thread([]() {
3165 pthread_setname_np(pthread_self(), "not_logd_thread");
3166 // Raise the signal on the side thread.
3167 raise_debugger_signal(kDebuggerdTombstone);
3168 });
3169 thread.join();
3170 _exit(0);
3171 });
3172
3173 unique_fd output_fd;
3174 StartIntercept(&output_fd, kDebuggerdTombstone);
3175 FinishCrasher();
3176 AssertDeath(0);
3177
3178 int intercept_result;
3179 FinishIntercept(&intercept_result);
3180 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3181
3182 std::string result;
3183 ConsumeFd(std::move(output_fd), &result);
3184 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
3185 ASSERT_NOT_MATCH(result, kLogMessage);
3186}
Christopher Ferris98d62422023-05-24 20:01:10 +00003187
3188// Disable this test since there is a high liklihood that this would
3189// be flaky since it requires 500 messages being in the log.
3190TEST_F(CrasherTest, DISABLED_max_log_messages) {
3191 StartProcess([]() {
3192 for (size_t i = 0; i < 600; i++) {
3193 LOG(INFO) << "Message number " << i;
3194 }
3195 abort();
3196 });
3197
3198 unique_fd output_fd;
3199 StartIntercept(&output_fd);
3200 FinishCrasher();
3201 AssertDeath(SIGABRT);
3202 int intercept_result;
3203 FinishIntercept(&intercept_result);
3204 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3205
3206 std::string result;
3207 ConsumeFd(std::move(output_fd), &result);
3208 ASSERT_NOT_MATCH(result, "Message number 99");
3209 ASSERT_MATCH(result, "Message number 100");
3210 ASSERT_MATCH(result, "Message number 599");
3211}
3212
3213TEST_F(CrasherTest, log_with_newline) {
3214 StartProcess([]() {
3215 LOG(INFO) << "This line has a newline.\nThis is on the next line.";
3216 abort();
3217 });
3218
3219 unique_fd output_fd;
3220 StartIntercept(&output_fd);
3221 FinishCrasher();
3222 AssertDeath(SIGABRT);
3223 int intercept_result;
3224 FinishIntercept(&intercept_result);
3225 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3226
3227 std::string result;
3228 ConsumeFd(std::move(output_fd), &result);
3229 ASSERT_MATCH(result, ":\\s*This line has a newline.");
3230 ASSERT_MATCH(result, ":\\s*This is on the next line.");
3231}