blob: 3135d9e503357f0384caa9d8f642f9763c25270d [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) {
606 // Because the detection of illegal setjmp is done relative to the SP in setjmp,
607 // we need to make sure this stack frame is bigger than the one of setjmp.
608 // TODO(fmayer): fix that bug and remove the workaround.
609 volatile char buf[1024];
610 buf[0] = '1';
611 setjmp(jump_buf);
612}
613
614TEST_F(CrasherTest, mte_illegal_setjmp) {
615 // This setjmp is illegal because it jumps back into a function that already returned.
616 // Quoting man 3 setjmp:
617 // If the function which called setjmp() returns before longjmp() is
618 // called, the behavior is undefined. Some kind of subtle or
619 // unsubtle chaos is sure to result.
620 // https://man7.org/linux/man-pages/man3/longjmp.3.html
621#if defined(__aarch64__)
622 if (!mte_supported()) {
623 GTEST_SKIP() << "Requires MTE";
624 }
625
626 int intercept_result;
627 unique_fd output_fd;
628 StartProcess([&]() {
629 SetTagCheckingLevelSync();
630 jmp_buf jump_buf;
631 mte_illegal_setjmp_helper(jump_buf);
632 longjmp(jump_buf, 1);
633 });
634
635 StartIntercept(&output_fd);
636 FinishCrasher();
637 AssertDeath(SIGABRT);
638 FinishIntercept(&intercept_result);
639
640 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
641
642 std::string result;
643 ConsumeFd(std::move(output_fd), &result);
644
645 // In our test-case, we have a NEGATIVE stack adjustment, which is being
646 // interpreted as unsigned integer, and thus is "too large".
647 // TODO(fmayer): fix the error message for this
648 ASSERT_MATCH(result, R"(memtag_handle_longjmp: stack adjustment too large)");
649#else
650 GTEST_SKIP() << "Requires aarch64";
651#endif
652}
653
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800654TEST_F(CrasherTest, mte_async) {
655#if defined(__aarch64__)
656 if (!mte_supported()) {
657 GTEST_SKIP() << "Requires MTE";
658 }
659
660 int intercept_result;
661 unique_fd output_fd;
662 StartProcess([&]() {
663 SetTagCheckingLevelAsync();
664 volatile int* p = (volatile int*)malloc(16);
665 p[-1] = 42;
666 });
667
668 StartIntercept(&output_fd);
669 FinishCrasher();
670 AssertDeath(SIGSEGV);
671 FinishIntercept(&intercept_result);
672
673 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
674
675 std::string result;
676 ConsumeFd(std::move(output_fd), &result);
677
Peter Collingbourne91e816a2023-03-07 21:24:47 -0800678 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code [89] \(SEGV_MTE[AS]ERR\), fault addr)");
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800679#else
680 GTEST_SKIP() << "Requires aarch64";
681#endif
682}
683
Peter Collingbournef8622522020-04-07 14:07:32 -0700684TEST_F(CrasherTest, mte_multiple_causes) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800685#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700686 if (!mte_supported()) {
687 GTEST_SKIP() << "Requires MTE";
688 }
689
Mitch Phillips78f06702021-06-01 14:35:43 -0700690 LogcatCollector logcat_collector;
691
Peter Collingbournef8622522020-04-07 14:07:32 -0700692 int intercept_result;
693 unique_fd output_fd;
694 StartProcess([]() {
695 SetTagCheckingLevelSync();
696
697 // Make two allocations with the same tag and close to one another. Check for both properties
698 // with a bounds check -- this relies on the fact that only if the allocations have the same tag
699 // would they be measured as closer than 128 bytes to each other. Otherwise they would be about
700 // (some non-zero value << 56) apart.
701 //
702 // The out-of-bounds access will be considered either an overflow of one or an underflow of the
703 // other.
704 std::set<uintptr_t> allocs;
705 for (int i = 0; i != 4096; ++i) {
706 uintptr_t alloc = reinterpret_cast<uintptr_t>(malloc(16));
707 auto it = allocs.insert(alloc).first;
708 if (it != allocs.begin() && *std::prev(it) + 128 > alloc) {
709 *reinterpret_cast<int*>(*std::prev(it) + 16) = 42;
710 }
711 if (std::next(it) != allocs.end() && alloc + 128 > *std::next(it)) {
712 *reinterpret_cast<int*>(alloc + 16) = 42;
713 }
714 }
715 });
716
717 StartIntercept(&output_fd);
718 FinishCrasher();
719 AssertDeath(SIGSEGV);
720 FinishIntercept(&intercept_result);
721
722 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
723
Mitch Phillips78f06702021-06-01 14:35:43 -0700724 std::vector<std::string> log_sources(2);
725 ConsumeFd(std::move(output_fd), &log_sources[0]);
726 logcat_collector.Collect(&log_sources[1]);
Peter Collingbournef8622522020-04-07 14:07:32 -0700727
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700728 // Tag dump only in the tombstone, not logcat.
729 ASSERT_MATCH(log_sources[0], "Memory tags around the fault address");
730
Mitch Phillips78f06702021-06-01 14:35:43 -0700731 for (const auto& result : log_sources) {
732 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
733 ASSERT_THAT(result, HasSubstr("Note: multiple potential causes for this crash were detected, "
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800734 "listing them in decreasing order of likelihood."));
Mitch Phillips78f06702021-06-01 14:35:43 -0700735 // Adjacent untracked allocations may cause us to see the wrong underflow here (or only
736 // overflows), so we can't match explicitly for an underflow message.
737 ASSERT_MATCH(result,
738 R"(Cause: \[MTE\]: Buffer Overflow, 0 bytes right of a 16-byte allocation)");
739 // Ensure there's at least two allocation traces (one for each cause).
740 ASSERT_MATCH(
741 result,
742 R"((^|\s)allocated by thread .*?\n.*#00 pc(.|\n)*?(^|\s)allocated by thread .*?\n.*#00 pc)");
743 }
Peter Collingbournef8622522020-04-07 14:07:32 -0700744#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800745 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournef8622522020-04-07 14:07:32 -0700746#endif
747}
748
Peter Collingbournecd278072020-12-21 14:08:38 -0800749#if defined(__aarch64__)
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700750static uintptr_t CreateTagMapping() {
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700751 // Some of the MTE tag dump tests assert that there is an inaccessible page to the left and right
752 // of the PROT_MTE page, so map three pages and set the two guard pages to PROT_NONE.
753 size_t page_size = getpagesize();
754 void* mapping = mmap(nullptr, page_size * 3, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
755 uintptr_t mapping_uptr = reinterpret_cast<uintptr_t>(mapping);
756 if (mapping == MAP_FAILED) {
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700757 return 0;
758 }
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700759 mprotect(reinterpret_cast<void*>(mapping_uptr + page_size), page_size,
760 PROT_READ | PROT_WRITE | PROT_MTE);
761 // Stripe the mapping, where even granules get tag '1', and odd granules get tag '0'.
762 for (uintptr_t offset = 0; offset < page_size; offset += 2 * kTagGranuleSize) {
763 uintptr_t tagged_addr = mapping_uptr + page_size + offset + (1ULL << 56);
764 __asm__ __volatile__(".arch_extension mte; stg %0, [%0]" : : "r"(tagged_addr) : "memory");
765 }
766 return mapping_uptr + page_size;
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700767}
768#endif
769
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700770TEST_F(CrasherTest, mte_register_tag_dump) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800771#if defined(__aarch64__)
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700772 if (!mte_supported()) {
773 GTEST_SKIP() << "Requires MTE";
774 }
775
776 int intercept_result;
777 unique_fd output_fd;
778 StartProcess([&]() {
779 SetTagCheckingLevelSync();
780 Trap(reinterpret_cast<void *>(CreateTagMapping()));
781 });
782
783 StartIntercept(&output_fd);
784 FinishCrasher();
Evgenii Stepanov361455e2022-10-13 16:23:08 -0700785 AssertDeath(SIGSEGV);
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700786 FinishIntercept(&intercept_result);
787
788 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
789
790 std::string result;
791 ConsumeFd(std::move(output_fd), &result);
792
793 ASSERT_MATCH(result, R"(memory near x0:
794.*
795.*
796 01.............0 0000000000000000 0000000000000000 ................
797 00.............0)");
798#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800799 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700800#endif
801}
802
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700803TEST_F(CrasherTest, mte_fault_tag_dump_front_truncated) {
804#if defined(__aarch64__)
805 if (!mte_supported()) {
806 GTEST_SKIP() << "Requires MTE";
807 }
808
809 int intercept_result;
810 unique_fd output_fd;
811 StartProcess([&]() {
812 SetTagCheckingLevelSync();
813 volatile char* p = reinterpret_cast<char*>(CreateTagMapping());
814 p[0] = 0; // Untagged pointer, tagged memory.
815 });
816
817 StartIntercept(&output_fd);
818 FinishCrasher();
819 AssertDeath(SIGSEGV);
820 FinishIntercept(&intercept_result);
821
822 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
823
824 std::string result;
825 ConsumeFd(std::move(output_fd), &result);
826
827 ASSERT_MATCH(result, R"(Memory tags around the fault address.*
828\s*=>0x[0-9a-f]+000:\[1\] 0 1 0)");
829#else
830 GTEST_SKIP() << "Requires aarch64";
831#endif
832}
833
834TEST_F(CrasherTest, mte_fault_tag_dump) {
835#if defined(__aarch64__)
836 if (!mte_supported()) {
837 GTEST_SKIP() << "Requires MTE";
838 }
839
840 int intercept_result;
841 unique_fd output_fd;
842 StartProcess([&]() {
843 SetTagCheckingLevelSync();
844 volatile char* p = reinterpret_cast<char*>(CreateTagMapping());
845 p[320] = 0; // Untagged pointer, tagged memory.
846 });
847
848 StartIntercept(&output_fd);
849 FinishCrasher();
850 AssertDeath(SIGSEGV);
851 FinishIntercept(&intercept_result);
852
853 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
854
855 std::string result;
856 ConsumeFd(std::move(output_fd), &result);
857
858 ASSERT_MATCH(result, R"(Memory tags around the fault address.*
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\s*0x[0-9a-f]+: 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
862)");
863#else
864 GTEST_SKIP() << "Requires aarch64";
865#endif
866}
867
868TEST_F(CrasherTest, mte_fault_tag_dump_rear_truncated) {
869#if defined(__aarch64__)
870 if (!mte_supported()) {
871 GTEST_SKIP() << "Requires MTE";
872 }
873
874 int intercept_result;
875 unique_fd output_fd;
876 StartProcess([&]() {
877 SetTagCheckingLevelSync();
878 size_t page_size = getpagesize();
879 volatile char* p = reinterpret_cast<char*>(CreateTagMapping());
880 p[page_size - kTagGranuleSize * 2] = 0; // Untagged pointer, tagged memory.
881 });
882
883 StartIntercept(&output_fd);
884 FinishCrasher();
885 AssertDeath(SIGSEGV);
886 FinishIntercept(&intercept_result);
887
888 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
889
890 std::string result;
891 ConsumeFd(std::move(output_fd), &result);
892
893 ASSERT_MATCH(result, R"(Memory tags around the fault address)");
894 ASSERT_MATCH(result,
895 R"(\s*0x[0-9a-f]+: 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
896\s*=>0x[0-9a-f]+: 1 0 1 0 1 0 1 0 1 0 1 0 1 0 \[1\] 0
897
898)"); // Ensure truncation happened and there's a newline after the tag fault.
899#else
900 GTEST_SKIP() << "Requires aarch64";
901#endif
902}
903
Josh Gaocdea7502017-11-01 15:00:40 -0700904TEST_F(CrasherTest, LD_PRELOAD) {
905 int intercept_result;
906 unique_fd output_fd;
907 StartProcess([]() {
908 setenv("LD_PRELOAD", "nonexistent.so", 1);
909 *reinterpret_cast<volatile char*>(0xdead) = '1';
910 });
911
912 StartIntercept(&output_fd);
913 FinishCrasher();
914 AssertDeath(SIGSEGV);
915 FinishIntercept(&intercept_result);
916
917 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
918
919 std::string result;
920 ConsumeFd(std::move(output_fd), &result);
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800921 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+dead)");
Josh Gaocdea7502017-11-01 15:00:40 -0700922}
923
Josh Gaocbe70cb2016-10-18 18:17:52 -0700924TEST_F(CrasherTest, abort) {
925 int intercept_result;
926 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -0800927 StartProcess([]() {
928 abort();
929 });
Josh Gaocbe70cb2016-10-18 18:17:52 -0700930 StartIntercept(&output_fd);
931 FinishCrasher();
932 AssertDeath(SIGABRT);
933 FinishIntercept(&intercept_result);
934
935 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
936
937 std::string result;
938 ConsumeFd(std::move(output_fd), &result);
Andreas Gampe26cbafb2017-06-22 20:14:43 -0700939 ASSERT_BACKTRACE_FRAME(result, "abort");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700940}
941
942TEST_F(CrasherTest, signal) {
943 int intercept_result;
944 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -0800945 StartProcess([]() {
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700946 while (true) {
947 sleep(1);
948 }
Josh Gao502cfd22017-02-17 01:39:15 -0800949 });
Josh Gaocbe70cb2016-10-18 18:17:52 -0700950 StartIntercept(&output_fd);
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700951 FinishCrasher();
Josh Gaocbe70cb2016-10-18 18:17:52 -0700952 ASSERT_EQ(0, kill(crasher_pid, SIGSEGV));
953
954 AssertDeath(SIGSEGV);
955 FinishIntercept(&intercept_result);
956
957 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
958
959 std::string result;
960 ConsumeFd(std::move(output_fd), &result);
Elliott Hughes89722702018-05-02 10:47:00 -0700961 ASSERT_MATCH(
962 result,
963 R"(signal 11 \(SIGSEGV\), code 0 \(SI_USER from pid \d+, uid \d+\), fault addr --------)");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700964 ASSERT_MATCH(result, R"(backtrace:)");
965}
966
967TEST_F(CrasherTest, abort_message) {
968 int intercept_result;
969 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -0800970 StartProcess([]() {
Josh Gao1cc7bd82018-02-13 13:16:17 -0800971 // Arrived at experimentally;
972 // logd truncates at 4062.
973 // strlen("Abort message: ''") is 17.
974 // That's 4045, but we also want a NUL.
975 char buf[4045 + 1];
976 memset(buf, 'x', sizeof(buf));
977 buf[sizeof(buf) - 1] = '\0';
978 android_set_abort_message(buf);
Josh Gao502cfd22017-02-17 01:39:15 -0800979 abort();
980 });
Josh Gaocbe70cb2016-10-18 18:17:52 -0700981 StartIntercept(&output_fd);
982 FinishCrasher();
983 AssertDeath(SIGABRT);
984 FinishIntercept(&intercept_result);
985
986 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
987
988 std::string result;
989 ConsumeFd(std::move(output_fd), &result);
Josh Gao1cc7bd82018-02-13 13:16:17 -0800990 ASSERT_MATCH(result, R"(Abort message: 'x{4045}')");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700991}
992
Florian Mayer5fa66632024-02-07 16:42:23 -0800993static char g_crash_detail_value_changes[] = "crash_detail_value";
994static char g_crash_detail_value[] = "crash_detail_value";
995static char g_crash_detail_value2[] = "crash_detail_value2";
996
997inline crash_detail_t* _Nullable android_register_crash_detail_strs(const char* _Nonnull name,
998 const char* _Nonnull data) {
Florian Mayer920d95b2024-02-14 12:57:09 -0800999 return android_crash_detail_register(name, strlen(name), data, strlen(data));
Florian Mayer5fa66632024-02-07 16:42:23 -08001000}
1001
1002TEST_F(CrasherTest, crash_detail_single) {
1003 int intercept_result;
1004 unique_fd output_fd;
1005 StartProcess([]() {
1006 android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value);
1007 abort();
1008 });
1009 StartIntercept(&output_fd);
1010 FinishCrasher();
1011 AssertDeath(SIGABRT);
1012 FinishIntercept(&intercept_result);
1013
1014 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1015
1016 std::string result;
1017 ConsumeFd(std::move(output_fd), &result);
1018 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'crash_detail_value')");
1019}
1020
Florian Mayeraced3aa2024-02-13 13:44:50 -08001021TEST_F(CrasherTest, crash_detail_replace_data) {
1022 int intercept_result;
1023 unique_fd output_fd;
1024 StartProcess([]() {
1025 auto *cd = android_register_crash_detail_strs("CRASH_DETAIL_NAME", "original_data");
Florian Mayer920d95b2024-02-14 12:57:09 -08001026 android_crash_detail_replace_data(cd, "new_data", strlen("new_data"));
Florian Mayeraced3aa2024-02-13 13:44:50 -08001027 abort();
1028 });
1029 StartIntercept(&output_fd);
1030 FinishCrasher();
1031 AssertDeath(SIGABRT);
1032 FinishIntercept(&intercept_result);
1033
1034 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1035
1036 std::string result;
1037 ConsumeFd(std::move(output_fd), &result);
1038 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'new_data')");
1039 // Ensure the old one no longer shows up, i.e. that we actually replaced
1040 // it, not added a new one.
1041 ASSERT_NOT_MATCH(result, R"(CRASH_DETAIL_NAME: 'original_data')");
1042}
1043
1044TEST_F(CrasherTest, crash_detail_replace_name) {
1045 int intercept_result;
1046 unique_fd output_fd;
1047 StartProcess([]() {
1048 auto *cd = android_register_crash_detail_strs("old_name", g_crash_detail_value);
Florian Mayer920d95b2024-02-14 12:57:09 -08001049 android_crash_detail_replace_name(cd, "new_name", strlen("new_name"));
Florian Mayeraced3aa2024-02-13 13:44:50 -08001050 abort();
1051 });
1052 StartIntercept(&output_fd);
1053 FinishCrasher();
1054 AssertDeath(SIGABRT);
1055 FinishIntercept(&intercept_result);
1056
1057 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1058
1059 std::string result;
1060 ConsumeFd(std::move(output_fd), &result);
1061 ASSERT_MATCH(result, R"(new_name: 'crash_detail_value')");
1062 // Ensure the old one no longer shows up, i.e. that we actually replaced
1063 // it, not added a new one.
1064 ASSERT_NOT_MATCH(result, R"(old_name: 'crash_detail_value')");
1065}
1066
Florian Mayer5fa66632024-02-07 16:42:23 -08001067TEST_F(CrasherTest, crash_detail_single_byte_name) {
1068 int intercept_result;
1069 unique_fd output_fd;
1070 StartProcess([]() {
1071 android_register_crash_detail_strs("CRASH_DETAIL_NAME\1", g_crash_detail_value);
1072 abort();
1073 });
1074 StartIntercept(&output_fd);
1075 FinishCrasher();
1076 AssertDeath(SIGABRT);
1077 FinishIntercept(&intercept_result);
1078
1079 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1080
1081 std::string result;
1082 ConsumeFd(std::move(output_fd), &result);
1083 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME\\1: 'crash_detail_value')");
1084}
1085
1086
1087TEST_F(CrasherTest, crash_detail_single_bytes) {
1088 int intercept_result;
1089 unique_fd output_fd;
1090 StartProcess([]() {
Florian Mayer920d95b2024-02-14 12:57:09 -08001091 android_crash_detail_register("CRASH_DETAIL_NAME", strlen("CRASH_DETAIL_NAME"), "\1",
Florian Mayer5fa66632024-02-07 16:42:23 -08001092 sizeof("\1"));
1093 abort();
1094 });
1095 StartIntercept(&output_fd);
1096 FinishCrasher();
1097 AssertDeath(SIGABRT);
1098 FinishIntercept(&intercept_result);
1099
1100 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1101
1102 std::string result;
1103 ConsumeFd(std::move(output_fd), &result);
1104 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: '\\1\\0')");
1105}
1106
1107TEST_F(CrasherTest, crash_detail_mixed) {
1108 int intercept_result;
1109 unique_fd output_fd;
1110 StartProcess([]() {
1111 const char data[] = "helloworld\1\255\3";
1112 android_register_crash_detail_strs("CRASH_DETAIL_NAME", data);
1113 abort();
1114 });
1115 StartIntercept(&output_fd);
1116 FinishCrasher();
1117 AssertDeath(SIGABRT);
1118 FinishIntercept(&intercept_result);
1119
1120 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1121
1122 std::string result;
1123 ConsumeFd(std::move(output_fd), &result);
1124 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'helloworld\\1\\255\\3')");
1125}
1126
1127TEST_F(CrasherTest, crash_detail_many) {
1128 int intercept_result;
1129 unique_fd output_fd;
1130 StartProcess([]() {
1131 for (int i = 0; i < 1000; ++i) {
1132 std::string name = "CRASH_DETAIL_NAME" + std::to_string(i);
1133 std::string value = "CRASH_DETAIL_VALUE" + std::to_string(i);
1134 auto* h = android_register_crash_detail_strs(name.data(), value.data());
Florian Mayer920d95b2024-02-14 12:57:09 -08001135 android_crash_detail_unregister(h);
Florian Mayer5fa66632024-02-07 16:42:23 -08001136 }
1137
1138 android_register_crash_detail_strs("FINAL_NAME", "FINAL_VALUE");
1139 android_register_crash_detail_strs("FINAL_NAME2", "FINAL_VALUE2");
1140 abort();
1141 });
1142 StartIntercept(&output_fd);
1143 FinishCrasher();
1144 AssertDeath(SIGABRT);
1145 FinishIntercept(&intercept_result);
1146
1147 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1148
1149 std::string result;
1150 ConsumeFd(std::move(output_fd), &result);
1151 ASSERT_NOT_MATCH(result, "CRASH_DETAIL_NAME");
1152 ASSERT_NOT_MATCH(result, "CRASH_DETAIL_VALUE");
1153 ASSERT_MATCH(result, R"(FINAL_NAME: 'FINAL_VALUE')");
1154 ASSERT_MATCH(result, R"(FINAL_NAME2: 'FINAL_VALUE2')");
1155}
1156
1157TEST_F(CrasherTest, crash_detail_single_changes) {
1158 int intercept_result;
1159 unique_fd output_fd;
1160 StartProcess([]() {
1161 android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value_changes);
1162 g_crash_detail_value_changes[0] = 'C';
1163 abort();
1164 });
1165 StartIntercept(&output_fd);
1166 FinishCrasher();
1167 AssertDeath(SIGABRT);
1168 FinishIntercept(&intercept_result);
1169
1170 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1171
1172 std::string result;
1173 ConsumeFd(std::move(output_fd), &result);
1174 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'Crash_detail_value')");
1175}
1176
1177TEST_F(CrasherTest, crash_detail_multiple) {
1178 int intercept_result;
1179 unique_fd output_fd;
1180 StartProcess([]() {
1181 android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value);
1182 android_register_crash_detail_strs("CRASH_DETAIL_NAME2", g_crash_detail_value2);
1183 abort();
1184 });
1185 StartIntercept(&output_fd);
1186 FinishCrasher();
1187 AssertDeath(SIGABRT);
1188 FinishIntercept(&intercept_result);
1189
1190 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1191
1192 std::string result;
1193 ConsumeFd(std::move(output_fd), &result);
1194 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'crash_detail_value')");
1195 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME2: 'crash_detail_value2')");
1196}
1197
1198TEST_F(CrasherTest, crash_detail_remove) {
1199 int intercept_result;
1200 unique_fd output_fd;
1201 StartProcess([]() {
1202 auto* detail1 = android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value);
Florian Mayer920d95b2024-02-14 12:57:09 -08001203 android_crash_detail_unregister(detail1);
Florian Mayer5fa66632024-02-07 16:42:23 -08001204 android_register_crash_detail_strs("CRASH_DETAIL_NAME2", g_crash_detail_value2);
1205 abort();
1206 });
1207 StartIntercept(&output_fd);
1208 FinishCrasher();
1209 AssertDeath(SIGABRT);
1210 FinishIntercept(&intercept_result);
1211
1212 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1213
1214 std::string result;
1215 ConsumeFd(std::move(output_fd), &result);
1216 ASSERT_NOT_MATCH(result, R"(CRASH_DETAIL_NAME: 'crash_detail_value')");
1217 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME2: 'crash_detail_value2')");
1218}
1219
Christopher Ferrise8891452021-08-17 17:34:53 -07001220TEST_F(CrasherTest, abort_message_newline_trimmed) {
1221 int intercept_result;
1222 unique_fd output_fd;
1223 StartProcess([]() {
1224 android_set_abort_message("Message with a newline.\n");
1225 abort();
1226 });
1227 StartIntercept(&output_fd);
1228 FinishCrasher();
1229 AssertDeath(SIGABRT);
1230 FinishIntercept(&intercept_result);
1231
1232 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1233
1234 std::string result;
1235 ConsumeFd(std::move(output_fd), &result);
1236 ASSERT_MATCH(result, R"(Abort message: 'Message with a newline.')");
1237}
1238
1239TEST_F(CrasherTest, abort_message_multiple_newlines_trimmed) {
1240 int intercept_result;
1241 unique_fd output_fd;
1242 StartProcess([]() {
1243 android_set_abort_message("Message with multiple newlines.\n\n\n\n\n");
1244 abort();
1245 });
1246 StartIntercept(&output_fd);
1247 FinishCrasher();
1248 AssertDeath(SIGABRT);
1249 FinishIntercept(&intercept_result);
1250
1251 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1252
1253 std::string result;
1254 ConsumeFd(std::move(output_fd), &result);
1255 ASSERT_MATCH(result, R"(Abort message: 'Message with multiple newlines.')");
1256}
1257
Josh Gaoe06f2a42017-04-27 16:50:38 -07001258TEST_F(CrasherTest, abort_message_backtrace) {
1259 int intercept_result;
1260 unique_fd output_fd;
1261 StartProcess([]() {
1262 android_set_abort_message("not actually aborting");
Josh Gaoa48b41b2019-12-13 14:11:04 -08001263 raise(BIONIC_SIGNAL_DEBUGGER);
Josh Gaoe06f2a42017-04-27 16:50:38 -07001264 exit(0);
1265 });
1266 StartIntercept(&output_fd);
1267 FinishCrasher();
1268 AssertDeath(0);
1269 FinishIntercept(&intercept_result);
1270
1271 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1272
1273 std::string result;
1274 ConsumeFd(std::move(output_fd), &result);
1275 ASSERT_NOT_MATCH(result, R"(Abort message:)");
1276}
1277
Josh Gaocbe70cb2016-10-18 18:17:52 -07001278TEST_F(CrasherTest, intercept_timeout) {
1279 int intercept_result;
1280 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -08001281 StartProcess([]() {
1282 abort();
1283 });
Josh Gaocbe70cb2016-10-18 18:17:52 -07001284 StartIntercept(&output_fd);
1285
1286 // Don't let crasher finish until we timeout.
1287 FinishIntercept(&intercept_result);
1288
1289 ASSERT_NE(1, intercept_result) << "tombstoned reported success? (intercept_result = "
1290 << intercept_result << ")";
1291
1292 FinishCrasher();
1293 AssertDeath(SIGABRT);
1294}
1295
Elliott Hughese4781d52021-03-17 09:15:15 -07001296TEST_F(CrasherTest, wait_for_debugger) {
1297 if (!android::base::SetProperty(kWaitForDebuggerKey, "1")) {
1298 FAIL() << "failed to enable wait_for_debugger";
Josh Gaocbe70cb2016-10-18 18:17:52 -07001299 }
1300 sleep(1);
1301
Josh Gao502cfd22017-02-17 01:39:15 -08001302 StartProcess([]() {
1303 abort();
1304 });
Josh Gaocbe70cb2016-10-18 18:17:52 -07001305 FinishCrasher();
1306
1307 int status;
Christopher Ferris172b0a02019-09-18 17:48:30 -07001308 ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, WUNTRACED)));
Josh Gaocbe70cb2016-10-18 18:17:52 -07001309 ASSERT_TRUE(WIFSTOPPED(status));
1310 ASSERT_EQ(SIGSTOP, WSTOPSIG(status));
1311
1312 ASSERT_EQ(0, kill(crasher_pid, SIGCONT));
1313
1314 AssertDeath(SIGABRT);
1315}
1316
Josh Gaocbe70cb2016-10-18 18:17:52 -07001317TEST_F(CrasherTest, backtrace) {
1318 std::string result;
1319 int intercept_result;
1320 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -08001321
1322 StartProcess([]() {
1323 abort();
1324 });
Narayan Kamatha73df602017-05-24 15:07:25 +01001325 StartIntercept(&output_fd, kDebuggerdNativeBacktrace);
Josh Gaocbe70cb2016-10-18 18:17:52 -07001326
1327 std::this_thread::sleep_for(500ms);
1328
1329 sigval val;
1330 val.sival_int = 1;
Josh Gaoa48b41b2019-12-13 14:11:04 -08001331 ASSERT_EQ(0, sigqueue(crasher_pid, BIONIC_SIGNAL_DEBUGGER, val)) << strerror(errno);
Josh Gaocbe70cb2016-10-18 18:17:52 -07001332 FinishIntercept(&intercept_result);
1333 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1334 ConsumeFd(std::move(output_fd), &result);
Jaesung Chung58778e12017-06-15 18:20:34 +09001335 ASSERT_BACKTRACE_FRAME(result, "read");
Josh Gaocbe70cb2016-10-18 18:17:52 -07001336
1337 int status;
1338 ASSERT_EQ(0, waitpid(crasher_pid, &status, WNOHANG | WUNTRACED));
1339
1340 StartIntercept(&output_fd);
1341 FinishCrasher();
1342 AssertDeath(SIGABRT);
1343 FinishIntercept(&intercept_result);
1344 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1345 ConsumeFd(std::move(output_fd), &result);
Andreas Gampe26cbafb2017-06-22 20:14:43 -07001346 ASSERT_BACKTRACE_FRAME(result, "abort");
Josh Gaocbe70cb2016-10-18 18:17:52 -07001347}
Josh Gaofca7ca32017-01-23 12:05:35 -08001348
1349TEST_F(CrasherTest, PR_SET_DUMPABLE_0_crash) {
Josh Gao502cfd22017-02-17 01:39:15 -08001350 int intercept_result;
1351 unique_fd output_fd;
Josh Gaofca7ca32017-01-23 12:05:35 -08001352 StartProcess([]() {
1353 prctl(PR_SET_DUMPABLE, 0);
Josh Gao502cfd22017-02-17 01:39:15 -08001354 abort();
Josh Gaofca7ca32017-01-23 12:05:35 -08001355 });
Josh Gao502cfd22017-02-17 01:39:15 -08001356
1357 StartIntercept(&output_fd);
1358 FinishCrasher();
1359 AssertDeath(SIGABRT);
1360 FinishIntercept(&intercept_result);
1361
1362 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1363
1364 std::string result;
1365 ConsumeFd(std::move(output_fd), &result);
Andreas Gampe26cbafb2017-06-22 20:14:43 -07001366 ASSERT_BACKTRACE_FRAME(result, "abort");
Josh Gaofca7ca32017-01-23 12:05:35 -08001367}
1368
Josh Gao502cfd22017-02-17 01:39:15 -08001369TEST_F(CrasherTest, capabilities) {
1370 ASSERT_EQ(0U, getuid()) << "capability test requires root";
1371
Josh Gaofca7ca32017-01-23 12:05:35 -08001372 StartProcess([]() {
Josh Gao502cfd22017-02-17 01:39:15 -08001373 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
1374 err(1, "failed to set PR_SET_KEEPCAPS");
1375 }
1376
1377 if (setresuid(1, 1, 1) != 0) {
1378 err(1, "setresuid failed");
1379 }
1380
1381 __user_cap_header_struct capheader;
1382 __user_cap_data_struct capdata[2];
1383 memset(&capheader, 0, sizeof(capheader));
1384 memset(&capdata, 0, sizeof(capdata));
1385
1386 capheader.version = _LINUX_CAPABILITY_VERSION_3;
1387 capheader.pid = 0;
1388
1389 // Turn on every third capability.
1390 static_assert(CAP_LAST_CAP > 33, "CAP_LAST_CAP <= 32");
1391 for (int i = 0; i < CAP_LAST_CAP; i += 3) {
1392 capdata[CAP_TO_INDEX(i)].permitted |= CAP_TO_MASK(i);
1393 capdata[CAP_TO_INDEX(i)].effective |= CAP_TO_MASK(i);
1394 }
1395
1396 // Make sure CAP_SYS_PTRACE is off.
1397 capdata[CAP_TO_INDEX(CAP_SYS_PTRACE)].permitted &= ~(CAP_TO_MASK(CAP_SYS_PTRACE));
1398 capdata[CAP_TO_INDEX(CAP_SYS_PTRACE)].effective &= ~(CAP_TO_MASK(CAP_SYS_PTRACE));
1399
1400 if (capset(&capheader, &capdata[0]) != 0) {
1401 err(1, "capset failed");
1402 }
1403
1404 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0) != 0) {
1405 err(1, "failed to drop ambient capabilities");
1406 }
1407
Josh Gaoa5199a92017-04-03 13:18:34 -07001408 pthread_setname_np(pthread_self(), "thread_name");
Josh Gao502cfd22017-02-17 01:39:15 -08001409 raise(SIGSYS);
Josh Gaofca7ca32017-01-23 12:05:35 -08001410 });
Josh Gao502cfd22017-02-17 01:39:15 -08001411
1412 unique_fd output_fd;
1413 StartIntercept(&output_fd);
1414 FinishCrasher();
1415 AssertDeath(SIGSYS);
1416
1417 std::string result;
1418 int intercept_result;
1419 FinishIntercept(&intercept_result);
1420 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1421 ConsumeFd(std::move(output_fd), &result);
Josh Gaoa5199a92017-04-03 13:18:34 -07001422 ASSERT_MATCH(result, R"(name: thread_name\s+>>> .+debuggerd_test(32|64) <<<)");
Jaesung Chung58778e12017-06-15 18:20:34 +09001423 ASSERT_BACKTRACE_FRAME(result, "tgkill");
Josh Gaofca7ca32017-01-23 12:05:35 -08001424}
Josh Gaoc3c8c022017-02-13 16:36:18 -08001425
Josh Gao2e7b8e22017-05-04 17:12:57 -07001426TEST_F(CrasherTest, fake_pid) {
1427 int intercept_result;
1428 unique_fd output_fd;
1429
1430 // Prime the getpid/gettid caches.
1431 UNUSED(getpid());
1432 UNUSED(gettid());
1433
1434 std::function<pid_t()> clone_fn = []() {
1435 return syscall(__NR_clone, SIGCHLD, nullptr, nullptr, nullptr, nullptr);
1436 };
1437 StartProcess(
1438 []() {
1439 ASSERT_NE(getpid(), syscall(__NR_getpid));
1440 ASSERT_NE(gettid(), syscall(__NR_gettid));
1441 raise(SIGSEGV);
1442 },
1443 clone_fn);
1444
1445 StartIntercept(&output_fd);
1446 FinishCrasher();
1447 AssertDeath(SIGSEGV);
1448 FinishIntercept(&intercept_result);
1449
1450 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1451
1452 std::string result;
1453 ConsumeFd(std::move(output_fd), &result);
Jaesung Chung58778e12017-06-15 18:20:34 +09001454 ASSERT_BACKTRACE_FRAME(result, "tgkill");
Josh Gao2e7b8e22017-05-04 17:12:57 -07001455}
1456
Josh Gaoe04ca272018-01-16 15:38:17 -08001457static const char* const kDebuggerdSeccompPolicy =
1458 "/system/etc/seccomp_policy/crash_dump." ABI_STRING ".policy";
1459
Mitch Phillips18ce5422023-01-19 14:23:49 -08001460static void setup_jail(minijail* jail) {
1461 if (!jail) {
1462 LOG(FATAL) << "failed to create minijail";
1463 }
1464
Josh Gao6f9eeec2018-09-12 13:55:47 -07001465 std::string policy;
1466 if (!android::base::ReadFileToString(kDebuggerdSeccompPolicy, &policy)) {
1467 PLOG(FATAL) << "failed to read policy file";
1468 }
1469
1470 // Allow a bunch of syscalls used by the tests.
1471 policy += "\nclone: 1";
1472 policy += "\nsigaltstack: 1";
1473 policy += "\nnanosleep: 1";
Christopher Ferrisab606682019-09-17 15:31:47 -07001474 policy += "\ngetrlimit: 1";
1475 policy += "\nugetrlimit: 1";
Josh Gao6f9eeec2018-09-12 13:55:47 -07001476
1477 FILE* tmp_file = tmpfile();
1478 if (!tmp_file) {
1479 PLOG(FATAL) << "tmpfile failed";
1480 }
1481
Christopher Ferris172b0a02019-09-18 17:48:30 -07001482 unique_fd tmp_fd(TEMP_FAILURE_RETRY(dup(fileno(tmp_file))));
Josh Gao6f9eeec2018-09-12 13:55:47 -07001483 if (!android::base::WriteStringToFd(policy, tmp_fd.get())) {
1484 PLOG(FATAL) << "failed to write policy to tmpfile";
1485 }
1486
1487 if (lseek(tmp_fd.get(), 0, SEEK_SET) != 0) {
1488 PLOG(FATAL) << "failed to seek tmp_fd";
Josh Gaoe04ca272018-01-16 15:38:17 -08001489 }
1490
Mitch Phillips18ce5422023-01-19 14:23:49 -08001491 minijail_no_new_privs(jail);
1492 minijail_log_seccomp_filter_failures(jail);
1493 minijail_use_seccomp_filter(jail);
1494 minijail_parse_seccomp_filters_from_fd(jail, tmp_fd.release());
1495}
Josh Gaoe04ca272018-01-16 15:38:17 -08001496
Mitch Phillips18ce5422023-01-19 14:23:49 -08001497static pid_t seccomp_fork_impl(void (*prejail)()) {
1498 ScopedMinijail jail{minijail_new()};
1499 setup_jail(jail.get());
Josh Gaoe04ca272018-01-16 15:38:17 -08001500
1501 pid_t result = fork();
1502 if (result == -1) {
1503 return result;
1504 } else if (result != 0) {
1505 return result;
1506 }
1507
1508 // Spawn and detach a thread that spins forever.
1509 std::atomic<bool> thread_ready(false);
1510 std::thread thread([&jail, &thread_ready]() {
1511 minijail_enter(jail.get());
1512 thread_ready = true;
1513 for (;;)
1514 ;
1515 });
1516 thread.detach();
1517
1518 while (!thread_ready) {
1519 continue;
1520 }
1521
Josh Gao70adac62018-02-22 11:38:33 -08001522 if (prejail) {
1523 prejail();
1524 }
1525
Josh Gaoe04ca272018-01-16 15:38:17 -08001526 minijail_enter(jail.get());
1527 return result;
1528}
1529
Josh Gao70adac62018-02-22 11:38:33 -08001530static pid_t seccomp_fork() {
1531 return seccomp_fork_impl(nullptr);
1532}
1533
Josh Gaoe04ca272018-01-16 15:38:17 -08001534TEST_F(CrasherTest, seccomp_crash) {
1535 int intercept_result;
1536 unique_fd output_fd;
1537
1538 StartProcess([]() { abort(); }, &seccomp_fork);
1539
1540 StartIntercept(&output_fd);
1541 FinishCrasher();
1542 AssertDeath(SIGABRT);
1543 FinishIntercept(&intercept_result);
1544 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1545
1546 std::string result;
1547 ConsumeFd(std::move(output_fd), &result);
1548 ASSERT_BACKTRACE_FRAME(result, "abort");
1549}
1550
Josh Gao70adac62018-02-22 11:38:33 -08001551static pid_t seccomp_fork_rlimit() {
1552 return seccomp_fork_impl([]() {
1553 struct rlimit rlim = {
1554 .rlim_cur = 512 * 1024 * 1024,
1555 .rlim_max = 512 * 1024 * 1024,
1556 };
1557
1558 if (setrlimit(RLIMIT_AS, &rlim) != 0) {
1559 raise(SIGINT);
1560 }
1561 });
1562}
1563
1564TEST_F(CrasherTest, seccomp_crash_oom) {
1565 int intercept_result;
1566 unique_fd output_fd;
1567
1568 StartProcess(
1569 []() {
1570 std::vector<void*> vec;
1571 for (int i = 0; i < 512; ++i) {
1572 char* buf = static_cast<char*>(malloc(1024 * 1024));
1573 if (!buf) {
1574 abort();
1575 }
1576 memset(buf, 0xff, 1024 * 1024);
1577 vec.push_back(buf);
1578 }
1579 },
1580 &seccomp_fork_rlimit);
1581
1582 StartIntercept(&output_fd);
1583 FinishCrasher();
1584 AssertDeath(SIGABRT);
1585 FinishIntercept(&intercept_result);
1586 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1587
1588 // We can't actually generate a backtrace, just make sure that the process terminates.
1589}
1590
Elliott Hughesb795d6f2022-09-14 20:15:19 +00001591__attribute__((__noinline__)) extern "C" bool raise_debugger_signal(DebuggerdDumpType dump_type) {
Josh Gaoe04ca272018-01-16 15:38:17 -08001592 siginfo_t siginfo;
1593 siginfo.si_code = SI_QUEUE;
1594 siginfo.si_pid = getpid();
1595 siginfo.si_uid = getuid();
1596
1597 if (dump_type != kDebuggerdNativeBacktrace && dump_type != kDebuggerdTombstone) {
1598 PLOG(FATAL) << "invalid dump type";
1599 }
1600
1601 siginfo.si_value.sival_int = dump_type == kDebuggerdNativeBacktrace;
1602
Josh Gaoa48b41b2019-12-13 14:11:04 -08001603 if (syscall(__NR_rt_tgsigqueueinfo, getpid(), gettid(), BIONIC_SIGNAL_DEBUGGER, &siginfo) != 0) {
Josh Gaoe04ca272018-01-16 15:38:17 -08001604 PLOG(ERROR) << "libdebuggerd_client: failed to send signal to self";
1605 return false;
1606 }
1607
1608 return true;
1609}
1610
Christopher Ferrisb999b822022-02-09 17:57:21 -08001611extern "C" void foo() {
1612 LOG(INFO) << "foo";
1613 std::this_thread::sleep_for(1s);
1614}
1615
1616extern "C" void bar() {
1617 LOG(INFO) << "bar";
1618 std::this_thread::sleep_for(1s);
1619}
1620
Josh Gaoe04ca272018-01-16 15:38:17 -08001621TEST_F(CrasherTest, seccomp_tombstone) {
1622 int intercept_result;
1623 unique_fd output_fd;
1624
1625 static const auto dump_type = kDebuggerdTombstone;
1626 StartProcess(
1627 []() {
Christopher Ferrisb999b822022-02-09 17:57:21 -08001628 std::thread a(foo);
1629 std::thread b(bar);
1630
1631 std::this_thread::sleep_for(100ms);
1632
Josh Gaoe04ca272018-01-16 15:38:17 -08001633 raise_debugger_signal(dump_type);
1634 _exit(0);
1635 },
1636 &seccomp_fork);
1637
1638 StartIntercept(&output_fd, dump_type);
1639 FinishCrasher();
1640 AssertDeath(0);
1641 FinishIntercept(&intercept_result);
1642 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1643
1644 std::string result;
1645 ConsumeFd(std::move(output_fd), &result);
1646 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
Christopher Ferrisb999b822022-02-09 17:57:21 -08001647 ASSERT_BACKTRACE_FRAME(result, "foo");
1648 ASSERT_BACKTRACE_FRAME(result, "bar");
Josh Gao6f9eeec2018-09-12 13:55:47 -07001649}
1650
Christopher Ferris303c6be2022-05-24 17:08:33 -07001651TEST_F(CrasherTest, seccomp_tombstone_thread_abort) {
1652 int intercept_result;
1653 unique_fd output_fd;
1654
1655 static const auto dump_type = kDebuggerdTombstone;
1656 StartProcess(
1657 []() {
1658 std::thread abort_thread([] { abort(); });
1659 abort_thread.join();
1660 },
1661 &seccomp_fork);
1662
1663 StartIntercept(&output_fd, dump_type);
1664 FinishCrasher();
1665 AssertDeath(SIGABRT);
1666 FinishIntercept(&intercept_result);
1667 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1668
1669 std::string result;
1670 ConsumeFd(std::move(output_fd), &result);
1671 ASSERT_BACKTRACE_FRAME(result, "abort");
1672}
1673
Christopher Ferris7c2e7e32022-05-27 12:57:58 -07001674TEST_F(CrasherTest, seccomp_tombstone_multiple_threads_abort) {
1675 int intercept_result;
1676 unique_fd output_fd;
1677
1678 static const auto dump_type = kDebuggerdTombstone;
1679 StartProcess(
1680 []() {
1681 std::thread a(foo);
1682 std::thread b(bar);
1683
1684 std::this_thread::sleep_for(100ms);
1685
1686 std::thread abort_thread([] { abort(); });
1687 abort_thread.join();
1688 },
1689 &seccomp_fork);
1690
1691 StartIntercept(&output_fd, dump_type);
1692 FinishCrasher();
1693 AssertDeath(SIGABRT);
1694 FinishIntercept(&intercept_result);
1695 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1696
1697 std::string result;
1698 ConsumeFd(std::move(output_fd), &result);
1699 ASSERT_BACKTRACE_FRAME(result, "abort");
1700 ASSERT_BACKTRACE_FRAME(result, "foo");
1701 ASSERT_BACKTRACE_FRAME(result, "bar");
1702 ASSERT_BACKTRACE_FRAME(result, "main");
1703}
1704
Josh Gaoe04ca272018-01-16 15:38:17 -08001705TEST_F(CrasherTest, seccomp_backtrace) {
1706 int intercept_result;
1707 unique_fd output_fd;
1708
1709 static const auto dump_type = kDebuggerdNativeBacktrace;
1710 StartProcess(
1711 []() {
Josh Gao6f9eeec2018-09-12 13:55:47 -07001712 std::thread a(foo);
1713 std::thread b(bar);
1714
1715 std::this_thread::sleep_for(100ms);
1716
Josh Gaoe04ca272018-01-16 15:38:17 -08001717 raise_debugger_signal(dump_type);
1718 _exit(0);
1719 },
1720 &seccomp_fork);
1721
1722 StartIntercept(&output_fd, dump_type);
1723 FinishCrasher();
1724 AssertDeath(0);
1725 FinishIntercept(&intercept_result);
1726 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1727
1728 std::string result;
1729 ConsumeFd(std::move(output_fd), &result);
1730 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
Josh Gao6f9eeec2018-09-12 13:55:47 -07001731 ASSERT_BACKTRACE_FRAME(result, "foo");
1732 ASSERT_BACKTRACE_FRAME(result, "bar");
Josh Gaoe04ca272018-01-16 15:38:17 -08001733}
1734
Christopher Ferris7c2e7e32022-05-27 12:57:58 -07001735TEST_F(CrasherTest, seccomp_backtrace_from_thread) {
1736 int intercept_result;
1737 unique_fd output_fd;
1738
1739 static const auto dump_type = kDebuggerdNativeBacktrace;
1740 StartProcess(
1741 []() {
1742 std::thread a(foo);
1743 std::thread b(bar);
1744
1745 std::this_thread::sleep_for(100ms);
1746
1747 std::thread raise_thread([] {
1748 raise_debugger_signal(dump_type);
1749 _exit(0);
1750 });
1751 raise_thread.join();
1752 },
1753 &seccomp_fork);
1754
1755 StartIntercept(&output_fd, dump_type);
1756 FinishCrasher();
1757 AssertDeath(0);
1758 FinishIntercept(&intercept_result);
1759 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1760
1761 std::string result;
1762 ConsumeFd(std::move(output_fd), &result);
1763 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
1764 ASSERT_BACKTRACE_FRAME(result, "foo");
1765 ASSERT_BACKTRACE_FRAME(result, "bar");
1766 ASSERT_BACKTRACE_FRAME(result, "main");
1767}
1768
Josh Gaoe04ca272018-01-16 15:38:17 -08001769TEST_F(CrasherTest, seccomp_crash_logcat) {
1770 StartProcess([]() { abort(); }, &seccomp_fork);
1771 FinishCrasher();
1772
1773 // Make sure we don't get SIGSYS when trying to dump a crash to logcat.
1774 AssertDeath(SIGABRT);
1775}
1776
Josh Gaofd13bf02017-08-18 15:37:26 -07001777TEST_F(CrasherTest, competing_tracer) {
1778 int intercept_result;
1779 unique_fd output_fd;
1780 StartProcess([]() {
Josh Gao2b2ae0c2017-08-21 14:31:17 -07001781 raise(SIGABRT);
Josh Gaofd13bf02017-08-18 15:37:26 -07001782 });
1783
1784 StartIntercept(&output_fd);
Josh Gaofd13bf02017-08-18 15:37:26 -07001785
1786 ASSERT_EQ(0, ptrace(PTRACE_SEIZE, crasher_pid, 0, 0));
Josh Gao2b2ae0c2017-08-21 14:31:17 -07001787 FinishCrasher();
Josh Gaofd13bf02017-08-18 15:37:26 -07001788
1789 int status;
Christopher Ferris172b0a02019-09-18 17:48:30 -07001790 ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
Josh Gaofd13bf02017-08-18 15:37:26 -07001791 ASSERT_TRUE(WIFSTOPPED(status));
1792 ASSERT_EQ(SIGABRT, WSTOPSIG(status));
1793
1794 ASSERT_EQ(0, ptrace(PTRACE_CONT, crasher_pid, 0, SIGABRT));
1795 FinishIntercept(&intercept_result);
1796 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1797
1798 std::string result;
1799 ConsumeFd(std::move(output_fd), &result);
1800 std::string regex = R"(failed to attach to thread \d+, already traced by )";
1801 regex += std::to_string(gettid());
1802 regex += R"( \(.+debuggerd_test)";
1803 ASSERT_MATCH(result, regex.c_str());
1804
Christopher Ferris172b0a02019-09-18 17:48:30 -07001805 ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
Josh Gao2b2ae0c2017-08-21 14:31:17 -07001806 ASSERT_TRUE(WIFSTOPPED(status));
1807 ASSERT_EQ(SIGABRT, WSTOPSIG(status));
1808
Josh Gaofd13bf02017-08-18 15:37:26 -07001809 ASSERT_EQ(0, ptrace(PTRACE_DETACH, crasher_pid, 0, SIGABRT));
1810 AssertDeath(SIGABRT);
1811}
1812
Mitch Phillips18ce5422023-01-19 14:23:49 -08001813struct GwpAsanTestParameters {
1814 size_t alloc_size;
1815 bool free_before_access;
1816 int access_offset;
1817 std::string cause_needle; // Needle to be found in the "Cause: [GWP-ASan]" line.
1818};
1819
1820struct GwpAsanCrasherTest
1821 : CrasherTest,
1822 testing::WithParamInterface<
1823 std::tuple<GwpAsanTestParameters, /* recoverable */ bool, /* seccomp */ bool>> {};
1824
1825GwpAsanTestParameters gwp_asan_tests[] = {
1826 {/* alloc_size */ 7, /* free_before_access */ true, /* access_offset */ 0,
1827 "Use After Free, 0 bytes into a 7-byte allocation"},
1828 {/* alloc_size */ 15, /* free_before_access */ true, /* access_offset */ 1,
1829 "Use After Free, 1 byte into a 15-byte allocation"},
1830 {/* alloc_size */ 4096, /* free_before_access */ false, /* access_offset */ 4098,
1831 "Buffer Overflow, 2 bytes right of a 4096-byte allocation"},
1832 {/* alloc_size */ 4096, /* free_before_access */ false, /* access_offset */ -1,
1833 "Buffer Underflow, 1 byte left of a 4096-byte allocation"},
1834};
1835
1836INSTANTIATE_TEST_SUITE_P(
1837 GwpAsanTests, GwpAsanCrasherTest,
1838 testing::Combine(testing::ValuesIn(gwp_asan_tests),
1839 /* recoverable */ testing::Bool(),
1840 /* seccomp */ testing::Bool()),
1841 [](const testing::TestParamInfo<
1842 std::tuple<GwpAsanTestParameters, /* recoverable */ bool, /* seccomp */ bool>>& info) {
1843 const GwpAsanTestParameters& params = std::get<0>(info.param);
1844 std::string name = params.free_before_access ? "UseAfterFree" : "Overflow";
1845 name += testing::PrintToString(params.alloc_size);
1846 name += "Alloc";
1847 if (params.access_offset < 0) {
1848 name += "Left";
1849 name += testing::PrintToString(params.access_offset * -1);
1850 } else {
1851 name += "Right";
1852 name += testing::PrintToString(params.access_offset);
1853 }
1854 name += "Bytes";
1855 if (std::get<1>(info.param)) name += "Recoverable";
1856 if (std::get<2>(info.param)) name += "Seccomp";
1857 return name;
1858 });
1859
1860TEST_P(GwpAsanCrasherTest, run_gwp_asan_test) {
1861 if (mte_supported()) {
1862 // Skip this test on MTE hardware, as MTE will reliably catch these errors
1863 // instead of GWP-ASan.
1864 GTEST_SKIP() << "Skipped on MTE.";
1865 }
1866 // Skip this test on HWASan, which will reliably catch test errors as well.
1867 SKIP_WITH_HWASAN;
1868
1869 GwpAsanTestParameters params = std::get<0>(GetParam());
1870 bool recoverable = std::get<1>(GetParam());
1871 LogcatCollector logcat_collector;
1872
1873 int intercept_result;
1874 unique_fd output_fd;
1875 StartProcess([&recoverable]() {
1876 const char* env[] = {"GWP_ASAN_SAMPLE_RATE=1", "GWP_ASAN_PROCESS_SAMPLING=1",
1877 "GWP_ASAN_MAX_ALLOCS=40000", nullptr, nullptr};
1878 if (recoverable) {
1879 env[3] = "GWP_ASAN_RECOVERABLE=true";
1880 }
1881 std::string test_name = ::testing::UnitTest::GetInstance()->current_test_info()->name();
1882 test_name = std::regex_replace(test_name, std::regex("run_gwp_asan_test"),
1883 "DISABLED_run_gwp_asan_test");
1884 std::string test_filter = "--gtest_filter=*";
1885 test_filter += test_name;
1886 std::string this_binary = android::base::GetExecutablePath();
1887 const char* args[] = {this_binary.c_str(), "--gtest_also_run_disabled_tests",
1888 test_filter.c_str(), nullptr};
1889 // We check the crash report from a debuggerd handler and from logcat. The
1890 // echo from stdout/stderr of the subprocess trips up atest, because it
1891 // doesn't like that two tests started in a row without the first one
1892 // finishing (even though the second one is in a subprocess).
1893 close(STDOUT_FILENO);
1894 close(STDERR_FILENO);
1895 execve(this_binary.c_str(), const_cast<char**>(args), const_cast<char**>(env));
1896 });
1897
1898 StartIntercept(&output_fd);
1899 FinishCrasher();
1900 if (recoverable) {
1901 AssertDeath(0);
1902 } else {
1903 AssertDeath(SIGSEGV);
1904 }
1905 FinishIntercept(&intercept_result);
1906
1907 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1908
1909 std::vector<std::string> log_sources(2);
1910 ConsumeFd(std::move(output_fd), &log_sources[0]);
1911 logcat_collector.Collect(&log_sources[1]);
1912
1913 // seccomp forces the fallback handler, which doesn't print GWP-ASan debugging
1914 // information. Make sure the recovery still works, but the report won't be
1915 // hugely useful, it looks like a regular SEGV.
1916 bool seccomp = std::get<2>(GetParam());
1917 if (!seccomp) {
1918 for (const auto& result : log_sources) {
1919 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\))");
1920 ASSERT_MATCH(result, R"(Cause: \[GWP-ASan\]: )" + params.cause_needle);
1921 if (params.free_before_access) {
1922 ASSERT_MATCH(result, R"(deallocated by thread .*\n.*#00 pc)");
1923 }
1924 ASSERT_MATCH(result, R"((^|\s)allocated by thread .*\n.*#00 pc)");
1925 }
1926 }
1927}
1928
1929TEST_P(GwpAsanCrasherTest, DISABLED_run_gwp_asan_test) {
1930 GwpAsanTestParameters params = std::get<0>(GetParam());
1931 bool seccomp = std::get<2>(GetParam());
1932 if (seccomp) {
1933 ScopedMinijail jail{minijail_new()};
1934 setup_jail(jail.get());
1935 minijail_enter(jail.get());
1936 }
1937
1938 // Use 'volatile' to prevent a very clever compiler eliminating the store.
1939 char* volatile p = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1940 if (params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
1941 p[params.access_offset] = 42;
1942 if (!params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
Mitch Phillips70aa2192023-02-22 11:31:36 -08001943
1944 bool recoverable = std::get<1>(GetParam());
1945 ASSERT_TRUE(recoverable); // Non-recoverable should have crashed.
1946
1947 // As we're in recoverable mode, trigger another 2x use-after-frees (ensuring
1948 // we end with at least one in a different slot), make sure the process still
1949 // doesn't crash.
1950 p = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1951 char* volatile p2 = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1952 free(static_cast<void*>(const_cast<char*>(p)));
1953 free(static_cast<void*>(const_cast<char*>(p2)));
1954 *p = 42;
1955 *p2 = 42;
1956
1957 // Under clang coverage (which is a default TEST_MAPPING presubmit target), the
1958 // recoverable+seccomp tests fail because the minijail prevents some atexit syscalls that clang
1959 // coverage does. Thus, skip the atexit handlers.
1960 _exit(0);
Mitch Phillips18ce5422023-01-19 14:23:49 -08001961}
1962
Josh Gaobf06a402018-08-27 16:34:01 -07001963TEST_F(CrasherTest, fdsan_warning_abort_message) {
1964 int intercept_result;
1965 unique_fd output_fd;
1966
1967 StartProcess([]() {
1968 android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
Christopher Ferris172b0a02019-09-18 17:48:30 -07001969 unique_fd fd(TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY | O_CLOEXEC)));
Josh Gaobf06a402018-08-27 16:34:01 -07001970 if (fd == -1) {
1971 abort();
1972 }
1973 close(fd.get());
1974 _exit(0);
1975 });
1976
1977 StartIntercept(&output_fd);
1978 FinishCrasher();
1979 AssertDeath(0);
1980 FinishIntercept(&intercept_result);
1981 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1982
1983 std::string result;
1984 ConsumeFd(std::move(output_fd), &result);
1985 ASSERT_MATCH(result, "Abort message: 'attempted to close");
1986}
1987
Josh Gaoc3c8c022017-02-13 16:36:18 -08001988TEST(crash_dump, zombie) {
1989 pid_t forkpid = fork();
1990
Josh Gaoc3c8c022017-02-13 16:36:18 -08001991 pid_t rc;
1992 int status;
1993
1994 if (forkpid == 0) {
1995 errno = 0;
1996 rc = waitpid(-1, &status, WNOHANG | __WALL | __WNOTHREAD);
1997 if (rc != -1 || errno != ECHILD) {
1998 errx(2, "first waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
1999 }
2000
Josh Gaoa48b41b2019-12-13 14:11:04 -08002001 raise(BIONIC_SIGNAL_DEBUGGER);
Josh Gaoc3c8c022017-02-13 16:36:18 -08002002
2003 errno = 0;
Christopher Ferris172b0a02019-09-18 17:48:30 -07002004 rc = TEMP_FAILURE_RETRY(waitpid(-1, &status, __WALL | __WNOTHREAD));
Josh Gaoc3c8c022017-02-13 16:36:18 -08002005 if (rc != -1 || errno != ECHILD) {
2006 errx(2, "second waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
2007 }
2008 _exit(0);
2009 } else {
Christopher Ferris172b0a02019-09-18 17:48:30 -07002010 rc = TEMP_FAILURE_RETRY(waitpid(forkpid, &status, 0));
Josh Gaoc3c8c022017-02-13 16:36:18 -08002011 ASSERT_EQ(forkpid, rc);
2012 ASSERT_TRUE(WIFEXITED(status));
2013 ASSERT_EQ(0, WEXITSTATUS(status));
2014 }
2015}
Josh Gao352a8452017-03-30 16:46:21 -07002016
2017TEST(tombstoned, no_notify) {
2018 // Do this a few times.
2019 for (int i = 0; i < 3; ++i) {
2020 pid_t pid = 123'456'789 + i;
2021
2022 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002023 InterceptResponse response = {};
2024 tombstoned_intercept(pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2025 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2026 << "Error message: " << response.error_message;
Josh Gao352a8452017-03-30 16:46:21 -07002027
2028 {
2029 unique_fd tombstoned_socket, input_fd;
Narayan Kamatha73df602017-05-24 15:07:25 +01002030 ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
Josh Gao352a8452017-03-30 16:46:21 -07002031 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid)));
2032 }
2033
2034 pid_t read_pid;
2035 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid)));
2036 ASSERT_EQ(read_pid, pid);
2037 }
2038}
2039
2040TEST(tombstoned, stress) {
2041 // Spawn threads to simultaneously do a bunch of failing dumps and a bunch of successful dumps.
2042 static constexpr int kDumpCount = 100;
2043
2044 std::atomic<bool> start(false);
2045 std::vector<std::thread> threads;
2046 threads.emplace_back([&start]() {
2047 while (!start) {
2048 continue;
2049 }
2050
2051 // Use a way out of range pid, to avoid stomping on an actual process.
2052 pid_t pid_base = 1'000'000;
2053
2054 for (int dump = 0; dump < kDumpCount; ++dump) {
2055 pid_t pid = pid_base + dump;
2056
2057 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002058 InterceptResponse response = {};
2059 tombstoned_intercept(pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2060 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2061 << "Error messeage: " << response.error_message;
Josh Gao352a8452017-03-30 16:46:21 -07002062
2063 // Pretend to crash, and then immediately close the socket.
2064 unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName,
2065 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
2066 if (sockfd == -1) {
2067 FAIL() << "failed to connect to tombstoned: " << strerror(errno);
2068 }
2069 TombstonedCrashPacket packet = {};
2070 packet.packet_type = CrashPacketType::kDumpRequest;
2071 packet.packet.dump_request.pid = pid;
2072 if (TEMP_FAILURE_RETRY(write(sockfd, &packet, sizeof(packet))) != sizeof(packet)) {
2073 FAIL() << "failed to write to tombstoned: " << strerror(errno);
2074 }
2075
2076 continue;
2077 }
2078 });
2079
2080 threads.emplace_back([&start]() {
2081 while (!start) {
2082 continue;
2083 }
2084
2085 // Use a way out of range pid, to avoid stomping on an actual process.
2086 pid_t pid_base = 2'000'000;
2087
2088 for (int dump = 0; dump < kDumpCount; ++dump) {
2089 pid_t pid = pid_base + dump;
2090
2091 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002092 InterceptResponse response = {};
2093 tombstoned_intercept(pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2094 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2095 << "Error message: " << response.error_message;
Josh Gao352a8452017-03-30 16:46:21 -07002096
2097 {
2098 unique_fd tombstoned_socket, input_fd;
Narayan Kamatha73df602017-05-24 15:07:25 +01002099 ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
Josh Gao352a8452017-03-30 16:46:21 -07002100 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid)));
2101 tombstoned_notify_completion(tombstoned_socket.get());
2102 }
2103
2104 // TODO: Fix the race that requires this sleep.
2105 std::this_thread::sleep_for(50ms);
2106
2107 pid_t read_pid;
2108 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid)));
2109 ASSERT_EQ(read_pid, pid);
2110 }
2111 });
2112
2113 start = true;
2114
2115 for (std::thread& thread : threads) {
2116 thread.join();
2117 }
2118}
Narayan Kamathca5e9082017-06-02 15:42:06 +01002119
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002120TEST(tombstoned, intercept_java_trace_smoke) {
Narayan Kamathca5e9082017-06-02 15:42:06 +01002121 // Using a "real" PID is a little dangerous here - if the test fails
2122 // or crashes, we might end up getting a bogus / unreliable stack
2123 // trace.
2124 const pid_t self = getpid();
2125
2126 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002127 InterceptResponse response = {};
2128 tombstoned_intercept(self, &intercept_fd, &output_fd, &response, kDebuggerdJavaBacktrace);
2129 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2130 << "Error message: " << response.error_message;
Narayan Kamathca5e9082017-06-02 15:42:06 +01002131
Josh Gao76e1e302021-01-26 15:53:11 -08002132 // First connect to tombstoned requesting a native tombstone. This
Narayan Kamathca5e9082017-06-02 15:42:06 +01002133 // should result in a "regular" FD and not the installed intercept.
2134 const char native[] = "native";
2135 unique_fd tombstoned_socket, input_fd;
Josh Gao76e1e302021-01-26 15:53:11 -08002136 ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
Narayan Kamathca5e9082017-06-02 15:42:06 +01002137 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), native, sizeof(native)));
2138 tombstoned_notify_completion(tombstoned_socket.get());
2139
2140 // Then, connect to tombstoned asking for a java backtrace. This *should*
2141 // trigger the intercept.
2142 const char java[] = "java";
2143 ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdJavaBacktrace));
2144 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), java, sizeof(java)));
2145 tombstoned_notify_completion(tombstoned_socket.get());
2146
2147 char outbuf[sizeof(java)];
2148 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
2149 ASSERT_STREQ("java", outbuf);
2150}
2151
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002152TEST(tombstoned, intercept_multiple_dump_types) {
Narayan Kamathca5e9082017-06-02 15:42:06 +01002153 const pid_t fake_pid = 1'234'567;
2154 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002155 InterceptResponse response = {};
2156 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdJavaBacktrace);
2157 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2158 << "Error message: " << response.error_message;
Narayan Kamathca5e9082017-06-02 15:42:06 +01002159
2160 unique_fd intercept_fd_2, output_fd_2;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002161 tombstoned_intercept(fake_pid, &intercept_fd_2, &output_fd_2, &response,
2162 kDebuggerdNativeBacktrace);
2163 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2164 << "Error message: " << response.error_message;
2165}
2166
2167TEST(tombstoned, intercept_bad_pid) {
2168 const pid_t fake_pid = -1;
2169 unique_fd intercept_fd, output_fd;
2170 InterceptResponse response = {};
2171 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdNativeBacktrace);
2172 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2173 << "Error message: " << response.error_message;
2174 ASSERT_MATCH(response.error_message, "bad pid");
2175}
2176
2177TEST(tombstoned, intercept_bad_dump_types) {
2178 const pid_t fake_pid = 1'234'567;
2179 unique_fd intercept_fd, output_fd;
2180 InterceptResponse response = {};
2181 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response,
2182 static_cast<DebuggerdDumpType>(20));
2183 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2184 << "Error message: " << response.error_message;
2185 ASSERT_MATCH(response.error_message, "bad dump type \\[unknown\\]");
2186
2187 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdAnyIntercept);
2188 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2189 << "Error message: " << response.error_message;
2190 ASSERT_MATCH(response.error_message, "bad dump type kDebuggerdAnyIntercept");
2191
2192 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstoneProto);
2193 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2194 << "Error message: " << response.error_message;
2195 ASSERT_MATCH(response.error_message, "bad dump type kDebuggerdTombstoneProto");
2196}
2197
2198TEST(tombstoned, intercept_already_registered) {
2199 const pid_t fake_pid = 1'234'567;
2200 unique_fd intercept_fd1, output_fd1;
2201 InterceptResponse response = {};
2202 tombstoned_intercept(fake_pid, &intercept_fd1, &output_fd1, &response, kDebuggerdTombstone);
2203 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2204 << "Error message: " << response.error_message;
2205
2206 unique_fd intercept_fd2, output_fd2;
2207 tombstoned_intercept(fake_pid, &intercept_fd2, &output_fd2, &response, kDebuggerdTombstone);
2208 ASSERT_EQ(InterceptStatus::kFailedAlreadyRegistered, response.status)
2209 << "Error message: " << response.error_message;
2210 ASSERT_MATCH(response.error_message, "already registered, type kDebuggerdTombstone");
2211}
2212
2213TEST(tombstoned, intercept_tombstone_proto_matched_to_tombstone) {
2214 const pid_t fake_pid = 1'234'567;
2215
2216 unique_fd intercept_fd, output_fd;
2217 InterceptResponse response = {};
2218 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2219 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2220 << "Error message: " << response.error_message;
2221
2222 const char data[] = "tombstone_proto";
2223 unique_fd tombstoned_socket, input_fd;
2224 ASSERT_TRUE(
2225 tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdTombstoneProto));
2226 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), data, sizeof(data)));
2227 tombstoned_notify_completion(tombstoned_socket.get());
2228
2229 char outbuf[sizeof(data)];
2230 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
2231 ASSERT_STREQ("tombstone_proto", outbuf);
Narayan Kamathca5e9082017-06-02 15:42:06 +01002232}
2233
2234TEST(tombstoned, intercept_any) {
2235 const pid_t fake_pid = 1'234'567;
2236
2237 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002238 InterceptResponse response = {};
2239 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdNativeBacktrace);
2240 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2241 << "Error message: " << response.error_message;
Narayan Kamathca5e9082017-06-02 15:42:06 +01002242
2243 const char any[] = "any";
2244 unique_fd tombstoned_socket, input_fd;
2245 ASSERT_TRUE(tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdAnyIntercept));
2246 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), any, sizeof(any)));
2247 tombstoned_notify_completion(tombstoned_socket.get());
2248
2249 char outbuf[sizeof(any)];
2250 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
2251 ASSERT_STREQ("any", outbuf);
2252}
Josh Gao2b22ae12018-09-12 14:51:03 -07002253
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002254TEST(tombstoned, intercept_any_failed_with_multiple_intercepts) {
2255 const pid_t fake_pid = 1'234'567;
2256
2257 InterceptResponse response = {};
2258 unique_fd intercept_fd1, output_fd1;
2259 tombstoned_intercept(fake_pid, &intercept_fd1, &output_fd1, &response, kDebuggerdNativeBacktrace);
2260 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2261 << "Error message: " << response.error_message;
2262
2263 unique_fd intercept_fd2, output_fd2;
2264 tombstoned_intercept(fake_pid, &intercept_fd2, &output_fd2, &response, kDebuggerdJavaBacktrace);
2265 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2266 << "Error message: " << response.error_message;
2267
2268 unique_fd tombstoned_socket, input_fd;
2269 ASSERT_FALSE(tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdAnyIntercept));
2270}
2271
2272TEST(tombstoned, intercept_multiple_verify_intercept) {
2273 // Need to use our pid for java since that will verify the pid.
2274 const pid_t fake_pid = getpid();
2275
2276 InterceptResponse response = {};
2277 unique_fd intercept_fd1, output_fd1;
2278 tombstoned_intercept(fake_pid, &intercept_fd1, &output_fd1, &response, kDebuggerdNativeBacktrace);
2279 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2280 << "Error message: " << response.error_message;
2281
2282 unique_fd intercept_fd2, output_fd2;
2283 tombstoned_intercept(fake_pid, &intercept_fd2, &output_fd2, &response, kDebuggerdJavaBacktrace);
2284 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2285 << "Error message: " << response.error_message;
2286
2287 unique_fd intercept_fd3, output_fd3;
2288 tombstoned_intercept(fake_pid, &intercept_fd3, &output_fd3, &response, kDebuggerdTombstone);
2289 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2290 << "Error message: " << response.error_message;
2291
2292 const char native_data[] = "native";
2293 unique_fd tombstoned_socket1, input_fd1;
2294 ASSERT_TRUE(
2295 tombstoned_connect(fake_pid, &tombstoned_socket1, &input_fd1, kDebuggerdNativeBacktrace));
2296 ASSERT_TRUE(android::base::WriteFully(input_fd1.get(), native_data, sizeof(native_data)));
2297 tombstoned_notify_completion(tombstoned_socket1.get());
2298
2299 char native_outbuf[sizeof(native_data)];
2300 ASSERT_TRUE(android::base::ReadFully(output_fd1.get(), native_outbuf, sizeof(native_outbuf)));
2301 ASSERT_STREQ("native", native_outbuf);
2302
2303 const char java_data[] = "java";
2304 unique_fd tombstoned_socket2, input_fd2;
2305 ASSERT_TRUE(
2306 tombstoned_connect(fake_pid, &tombstoned_socket2, &input_fd2, kDebuggerdJavaBacktrace));
2307 ASSERT_TRUE(android::base::WriteFully(input_fd2.get(), java_data, sizeof(java_data)));
2308 tombstoned_notify_completion(tombstoned_socket2.get());
2309
2310 char java_outbuf[sizeof(java_data)];
2311 ASSERT_TRUE(android::base::ReadFully(output_fd2.get(), java_outbuf, sizeof(java_outbuf)));
2312 ASSERT_STREQ("java", java_outbuf);
2313
2314 const char tomb_data[] = "tombstone";
2315 unique_fd tombstoned_socket3, input_fd3;
2316 ASSERT_TRUE(tombstoned_connect(fake_pid, &tombstoned_socket3, &input_fd3, kDebuggerdTombstone));
2317 ASSERT_TRUE(android::base::WriteFully(input_fd3.get(), tomb_data, sizeof(tomb_data)));
2318 tombstoned_notify_completion(tombstoned_socket3.get());
2319
2320 char tomb_outbuf[sizeof(tomb_data)];
2321 ASSERT_TRUE(android::base::ReadFully(output_fd3.get(), tomb_outbuf, sizeof(tomb_outbuf)));
2322 ASSERT_STREQ("tombstone", tomb_outbuf);
2323}
2324
Josh Gao2b22ae12018-09-12 14:51:03 -07002325TEST(tombstoned, interceptless_backtrace) {
2326 // Generate 50 backtraces, and then check to see that we haven't created 50 new tombstones.
2327 auto get_tombstone_timestamps = []() -> std::map<int, time_t> {
2328 std::map<int, time_t> result;
2329 for (int i = 0; i < 99; ++i) {
2330 std::string path = android::base::StringPrintf("/data/tombstones/tombstone_%02d", i);
2331 struct stat st;
2332 if (stat(path.c_str(), &st) == 0) {
2333 result[i] = st.st_mtim.tv_sec;
2334 }
2335 }
2336 return result;
2337 };
2338
2339 auto before = get_tombstone_timestamps();
2340 for (int i = 0; i < 50; ++i) {
2341 raise_debugger_signal(kDebuggerdNativeBacktrace);
2342 }
2343 auto after = get_tombstone_timestamps();
2344
2345 int diff = 0;
2346 for (int i = 0; i < 99; ++i) {
2347 if (after.count(i) == 0) {
2348 continue;
2349 }
2350 if (before.count(i) == 0) {
2351 ++diff;
2352 continue;
2353 }
2354 if (before[i] != after[i]) {
2355 ++diff;
2356 }
2357 }
2358
2359 // We can't be sure that nothing's crash looping in the background.
2360 // This should be good enough, though...
2361 ASSERT_LT(diff, 10) << "too many new tombstones; is something crashing in the background?";
2362}
Christopher Ferris481e8372019-07-15 17:13:24 -07002363
2364static __attribute__((__noinline__)) void overflow_stack(void* p) {
2365 void* buf[1];
2366 buf[0] = p;
2367 static volatile void* global = buf;
2368 if (global) {
2369 global = buf;
2370 overflow_stack(&buf);
2371 }
2372}
2373
2374TEST_F(CrasherTest, stack_overflow) {
2375 int intercept_result;
2376 unique_fd output_fd;
2377 StartProcess([]() { overflow_stack(nullptr); });
2378
2379 StartIntercept(&output_fd);
2380 FinishCrasher();
2381 AssertDeath(SIGSEGV);
2382 FinishIntercept(&intercept_result);
2383
2384 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2385
2386 std::string result;
2387 ConsumeFd(std::move(output_fd), &result);
2388 ASSERT_MATCH(result, R"(Cause: stack pointer[^\n]*stack overflow.\n)");
2389}
Josh Gao76e1e302021-01-26 15:53:11 -08002390
Christopher Ferris22035cc2023-01-31 17:50:22 -08002391static std::string GetTestLibraryPath() {
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002392 std::string test_lib(testing::internal::GetArgvs()[0]);
2393 auto const value = test_lib.find_last_of('/');
2394 if (value == std::string::npos) {
2395 test_lib = "./";
2396 } else {
2397 test_lib = test_lib.substr(0, value + 1) + "./";
2398 }
Christopher Ferris22035cc2023-01-31 17:50:22 -08002399 return test_lib + "libcrash_test.so";
2400}
2401
2402static void CreateEmbeddedLibrary(int out_fd) {
2403 std::string test_lib(GetTestLibraryPath());
2404 android::base::unique_fd fd(open(test_lib.c_str(), O_RDONLY | O_CLOEXEC));
2405 ASSERT_NE(fd.get(), -1);
2406 off_t file_size = lseek(fd, 0, SEEK_END);
2407 ASSERT_EQ(lseek(fd, 0, SEEK_SET), 0);
2408 std::vector<uint8_t> contents(file_size);
2409 ASSERT_TRUE(android::base::ReadFully(fd, contents.data(), contents.size()));
2410
2411 // Put the shared library data at a pagesize() offset.
2412 ASSERT_EQ(lseek(out_fd, 4 * getpagesize(), SEEK_CUR), 4 * getpagesize());
2413 ASSERT_EQ(static_cast<size_t>(write(out_fd, contents.data(), contents.size())), contents.size());
2414}
2415
2416TEST_F(CrasherTest, non_zero_offset_in_library) {
2417 int intercept_result;
2418 unique_fd output_fd;
2419 TemporaryFile tf;
2420 CreateEmbeddedLibrary(tf.fd);
2421 StartProcess([&tf]() {
2422 android_dlextinfo extinfo{};
2423 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
2424 extinfo.library_fd = tf.fd;
2425 extinfo.library_fd_offset = 4 * getpagesize();
2426 void* handle = android_dlopen_ext(tf.path, RTLD_NOW, &extinfo);
2427 if (handle == nullptr) {
2428 _exit(1);
2429 }
2430 void (*crash_func)() = reinterpret_cast<void (*)()>(dlsym(handle, "crash"));
2431 if (crash_func == nullptr) {
2432 _exit(1);
2433 }
2434 crash_func();
2435 });
2436
2437 StartIntercept(&output_fd);
2438 FinishCrasher();
2439 AssertDeath(SIGSEGV);
2440 FinishIntercept(&intercept_result);
2441
2442 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2443
2444 std::string result;
2445 ConsumeFd(std::move(output_fd), &result);
2446
2447 // Verify the crash includes an offset value in the backtrace.
2448 std::string match_str = android::base::StringPrintf("%s\\!libcrash_test.so \\(offset 0x%x\\)",
2449 tf.path, 4 * getpagesize());
2450 ASSERT_MATCH(result, match_str);
2451}
2452
2453static bool CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) {
2454 std::string test_lib(GetTestLibraryPath());
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002455
2456 *tmp_so_name = std::string(tmp_dir) + "/libcrash_test.so";
2457 std::string cp_cmd = android::base::StringPrintf("cp %s %s", test_lib.c_str(), tmp_dir);
2458
2459 // Copy the shared so to a tempory directory.
2460 return system(cp_cmd.c_str()) == 0;
2461}
2462
2463TEST_F(CrasherTest, unreadable_elf) {
2464 int intercept_result;
2465 unique_fd output_fd;
Christopher Ferrisc95047d2022-03-14 15:02:11 -07002466 std::string tmp_so_name;
2467 StartProcess([&tmp_so_name]() {
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002468 TemporaryDir td;
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002469 if (!CopySharedLibrary(td.path, &tmp_so_name)) {
2470 _exit(1);
2471 }
2472 void* handle = dlopen(tmp_so_name.c_str(), RTLD_NOW);
2473 if (handle == nullptr) {
2474 _exit(1);
2475 }
2476 // Delete the original shared library so that we get the warning
2477 // about unreadable elf files.
2478 if (unlink(tmp_so_name.c_str()) == -1) {
2479 _exit(1);
2480 }
2481 void (*crash_func)() = reinterpret_cast<void (*)()>(dlsym(handle, "crash"));
2482 if (crash_func == nullptr) {
2483 _exit(1);
2484 }
2485 crash_func();
2486 });
2487
2488 StartIntercept(&output_fd);
2489 FinishCrasher();
2490 AssertDeath(SIGSEGV);
2491 FinishIntercept(&intercept_result);
2492
2493 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2494
2495 std::string result;
2496 ConsumeFd(std::move(output_fd), &result);
2497 ASSERT_MATCH(result, R"(NOTE: Function names and BuildId information is missing )");
Christopher Ferrisc95047d2022-03-14 15:02:11 -07002498 std::string match_str = "NOTE: " + tmp_so_name;
2499 ASSERT_MATCH(result, match_str);
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002500}
2501
Christopher Ferris20f50ec2024-01-03 02:30:03 +00002502void CheckForTombstone(const struct stat& text_st, std::optional<std::string>& tombstone_file) {
2503 static std::regex tombstone_re("tombstone_\\d+");
Christopher Ferris35da2882021-02-17 15:39:06 -08002504 std::unique_ptr<DIR, decltype(&closedir)> dir_h(opendir("/data/tombstones"), closedir);
2505 ASSERT_TRUE(dir_h != nullptr);
Christopher Ferris35da2882021-02-17 15:39:06 -08002506 dirent* entry;
2507 while ((entry = readdir(dir_h.get())) != nullptr) {
2508 if (!std::regex_match(entry->d_name, tombstone_re)) {
2509 continue;
2510 }
2511 std::string path = android::base::StringPrintf("/data/tombstones/%s", entry->d_name);
Josh Gao76e1e302021-01-26 15:53:11 -08002512
2513 struct stat st;
2514 if (TEMP_FAILURE_RETRY(stat(path.c_str(), &st)) != 0) {
2515 continue;
2516 }
2517
2518 if (st.st_dev == text_st.st_dev && st.st_ino == text_st.st_ino) {
Christopher Ferris35da2882021-02-17 15:39:06 -08002519 tombstone_file = path;
Josh Gao76e1e302021-01-26 15:53:11 -08002520 break;
2521 }
2522 }
Christopher Ferris20f50ec2024-01-03 02:30:03 +00002523}
Josh Gao76e1e302021-01-26 15:53:11 -08002524
Christopher Ferris20f50ec2024-01-03 02:30:03 +00002525TEST(tombstoned, proto) {
2526 const pid_t self = getpid();
2527 unique_fd tombstoned_socket, text_fd, proto_fd;
2528 ASSERT_TRUE(
2529 tombstoned_connect(self, &tombstoned_socket, &text_fd, &proto_fd, kDebuggerdTombstoneProto));
2530
2531 tombstoned_notify_completion(tombstoned_socket.get());
2532
2533 ASSERT_NE(-1, text_fd.get());
2534 ASSERT_NE(-1, proto_fd.get());
2535
2536 struct stat text_st;
2537 ASSERT_EQ(0, fstat(text_fd.get(), &text_st));
2538
2539 std::optional<std::string> tombstone_file;
2540 // Allow up to 5 seconds for the tombstone to be written to the system.
2541 const auto max_wait_time = std::chrono::seconds(5) * android::base::HwTimeoutMultiplier();
2542 const auto start = std::chrono::high_resolution_clock::now();
2543 while (true) {
2544 std::this_thread::sleep_for(100ms);
2545 CheckForTombstone(text_st, tombstone_file);
2546 if (tombstone_file) {
2547 break;
2548 }
2549 if (std::chrono::high_resolution_clock::now() - start > max_wait_time) {
2550 break;
2551 }
2552 }
2553
2554 ASSERT_TRUE(tombstone_file) << "Timed out trying to find tombstone file.";
Christopher Ferris35da2882021-02-17 15:39:06 -08002555 std::string proto_path = tombstone_file.value() + ".pb";
Josh Gao76e1e302021-01-26 15:53:11 -08002556
2557 struct stat proto_fd_st;
2558 struct stat proto_file_st;
2559 ASSERT_EQ(0, fstat(proto_fd.get(), &proto_fd_st));
2560 ASSERT_EQ(0, stat(proto_path.c_str(), &proto_file_st));
2561
2562 ASSERT_EQ(proto_fd_st.st_dev, proto_file_st.st_dev);
2563 ASSERT_EQ(proto_fd_st.st_ino, proto_file_st.st_ino);
2564}
2565
2566TEST(tombstoned, proto_intercept) {
2567 const pid_t self = getpid();
2568 unique_fd intercept_fd, output_fd;
Josh Gao76e1e302021-01-26 15:53:11 -08002569
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002570 InterceptResponse response = {};
2571 tombstoned_intercept(self, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2572 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2573 << "Error message: " << response.error_message;
Josh Gao76e1e302021-01-26 15:53:11 -08002574
2575 unique_fd tombstoned_socket, text_fd, proto_fd;
2576 ASSERT_TRUE(
2577 tombstoned_connect(self, &tombstoned_socket, &text_fd, &proto_fd, kDebuggerdTombstoneProto));
2578 ASSERT_TRUE(android::base::WriteStringToFd("foo", text_fd.get()));
2579 tombstoned_notify_completion(tombstoned_socket.get());
2580
2581 text_fd.reset();
2582
2583 std::string output;
2584 ASSERT_TRUE(android::base::ReadFdToString(output_fd, &output));
2585 ASSERT_EQ("foo", output);
2586}
Christopher Ferrisa3e9a0b2021-07-29 12:38:07 -07002587
2588// Verify that when an intercept is present for the main thread, and the signal
2589// is received on a different thread, the intercept still works.
2590TEST_F(CrasherTest, intercept_for_main_thread_signal_on_side_thread) {
2591 StartProcess([]() {
2592 std::thread thread([]() {
2593 // Raise the signal on the side thread.
2594 raise_debugger_signal(kDebuggerdNativeBacktrace);
2595 });
2596 thread.join();
2597 _exit(0);
2598 });
2599
2600 unique_fd output_fd;
2601 StartIntercept(&output_fd, kDebuggerdNativeBacktrace);
2602 FinishCrasher();
2603 AssertDeath(0);
2604
2605 int intercept_result;
2606 FinishIntercept(&intercept_result);
2607 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2608
2609 std::string result;
2610 ConsumeFd(std::move(output_fd), &result);
2611 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
2612}
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002613
2614static std::string format_pointer(uintptr_t ptr) {
2615#if defined(__LP64__)
2616 return android::base::StringPrintf("%08x'%08x", static_cast<uint32_t>(ptr >> 32),
2617 static_cast<uint32_t>(ptr & 0xffffffff));
2618#else
2619 return android::base::StringPrintf("%08x", static_cast<uint32_t>(ptr & 0xffffffff));
2620#endif
2621}
2622
2623static std::string format_pointer(void* ptr) {
2624 return format_pointer(reinterpret_cast<uintptr_t>(ptr));
2625}
2626
2627static std::string format_full_pointer(uintptr_t ptr) {
2628#if defined(__LP64__)
2629 return android::base::StringPrintf("%016" PRIx64, ptr);
2630#else
2631 return android::base::StringPrintf("%08x", ptr);
2632#endif
2633}
2634
2635static std::string format_full_pointer(void* ptr) {
2636 return format_full_pointer(reinterpret_cast<uintptr_t>(ptr));
2637}
2638
2639__attribute__((__noinline__)) int crash_call(uintptr_t ptr) {
2640 int* crash_ptr = reinterpret_cast<int*>(ptr);
2641 *crash_ptr = 1;
2642 return *crash_ptr;
2643}
2644
2645// Verify that a fault address before the first map is properly handled.
2646TEST_F(CrasherTest, fault_address_before_first_map) {
2647 StartProcess([]() {
2648 ASSERT_EQ(0, crash_call(0x1024));
2649 _exit(0);
2650 });
2651
2652 unique_fd output_fd;
2653 StartIntercept(&output_fd);
2654 FinishCrasher();
2655 AssertDeath(SIGSEGV);
2656
2657 int intercept_result;
2658 FinishIntercept(&intercept_result);
2659 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2660
2661 std::string result;
2662 ConsumeFd(std::move(output_fd), &result);
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002663 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+1024)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002664
2665 ASSERT_MATCH(result, R"(\nmemory map \(.*\):\n)");
2666
2667 std::string match_str = android::base::StringPrintf(
2668 R"(memory map .*:\n--->Fault address falls at %s before any mapped regions\n )",
2669 format_pointer(0x1024).c_str());
2670 ASSERT_MATCH(result, match_str);
2671}
2672
2673// Verify that a fault address after the last map is properly handled.
2674TEST_F(CrasherTest, fault_address_after_last_map) {
Florian Mayerb4979292022-04-15 14:35:17 -07002675 // This makes assumptions about the memory layout that are not true in HWASan
2676 // processes.
2677 SKIP_WITH_HWASAN;
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002678 uintptr_t crash_uptr = untag_address(UINTPTR_MAX - 15);
2679 StartProcess([crash_uptr]() {
2680 ASSERT_EQ(0, crash_call(crash_uptr));
2681 _exit(0);
2682 });
2683
2684 unique_fd output_fd;
2685 StartIntercept(&output_fd);
2686 FinishCrasher();
2687 AssertDeath(SIGSEGV);
2688
2689 int intercept_result;
2690 FinishIntercept(&intercept_result);
2691 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2692
2693 std::string result;
2694 ConsumeFd(std::move(output_fd), &result);
2695
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002696 std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x)";
2697 match_str += format_full_pointer(crash_uptr);
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002698 ASSERT_MATCH(result, match_str);
2699
Ryan Prichardbc227032024-02-29 14:40:57 -08002700 ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002701
Christopher Ferris3a0833c2023-07-28 13:07:53 -07002702 // Verifies that the fault address error message is at the end of the
2703 // maps section. To do this, the check below looks for the start of the
2704 // open files section or the start of the log file section. It's possible
2705 // for either of these sections to be present after the maps section right
2706 // now.
2707 // If the sections move around, this check might need to be modified.
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002708 match_str = android::base::StringPrintf(
Christopher Ferris3a0833c2023-07-28 13:07:53 -07002709 R"(\n--->Fault address falls at %s after any mapped regions\n(---------|\nopen files:))",
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002710 format_pointer(crash_uptr).c_str());
2711 ASSERT_MATCH(result, match_str);
2712}
2713
2714// Verify that a fault address between maps is properly handled.
2715TEST_F(CrasherTest, fault_address_between_maps) {
2716 // Create a map before the fork so it will be present in the child.
2717 void* start_ptr =
2718 mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2719 ASSERT_NE(MAP_FAILED, start_ptr);
2720 // Unmap the page in the middle.
2721 void* middle_ptr =
2722 reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start_ptr) + getpagesize());
2723 ASSERT_EQ(0, munmap(middle_ptr, getpagesize()));
2724
2725 StartProcess([middle_ptr]() {
2726 ASSERT_EQ(0, crash_call(reinterpret_cast<uintptr_t>(middle_ptr)));
2727 _exit(0);
2728 });
2729
2730 // Unmap the two maps.
2731 ASSERT_EQ(0, munmap(start_ptr, getpagesize()));
2732 void* end_ptr =
2733 reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start_ptr) + 2 * getpagesize());
2734 ASSERT_EQ(0, munmap(end_ptr, getpagesize()));
2735
2736 unique_fd output_fd;
2737 StartIntercept(&output_fd);
2738 FinishCrasher();
2739 AssertDeath(SIGSEGV);
2740
2741 int intercept_result;
2742 FinishIntercept(&intercept_result);
2743 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2744
2745 std::string result;
2746 ConsumeFd(std::move(output_fd), &result);
2747
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002748 std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x)";
2749 match_str += format_full_pointer(reinterpret_cast<uintptr_t>(middle_ptr));
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002750 ASSERT_MATCH(result, match_str);
2751
Ryan Prichardbc227032024-02-29 14:40:57 -08002752 ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002753
2754 match_str = android::base::StringPrintf(
2755 R"( %s.*\n--->Fault address falls at %s between mapped regions\n %s)",
2756 format_pointer(start_ptr).c_str(), format_pointer(middle_ptr).c_str(),
2757 format_pointer(end_ptr).c_str());
2758 ASSERT_MATCH(result, match_str);
2759}
2760
2761// Verify that a fault address happens in the correct map.
2762TEST_F(CrasherTest, fault_address_in_map) {
2763 // Create a map before the fork so it will be present in the child.
2764 void* ptr = mmap(nullptr, getpagesize(), 0, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2765 ASSERT_NE(MAP_FAILED, ptr);
2766
2767 StartProcess([ptr]() {
2768 ASSERT_EQ(0, crash_call(reinterpret_cast<uintptr_t>(ptr)));
2769 _exit(0);
2770 });
2771
2772 ASSERT_EQ(0, munmap(ptr, getpagesize()));
2773
2774 unique_fd output_fd;
2775 StartIntercept(&output_fd);
2776 FinishCrasher();
2777 AssertDeath(SIGSEGV);
2778
2779 int intercept_result;
2780 FinishIntercept(&intercept_result);
2781 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2782
2783 std::string result;
2784 ConsumeFd(std::move(output_fd), &result);
2785
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002786 std::string match_str = R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\), fault addr 0x)";
2787 match_str += format_full_pointer(reinterpret_cast<uintptr_t>(ptr));
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002788 ASSERT_MATCH(result, match_str);
2789
Ryan Prichardbc227032024-02-29 14:40:57 -08002790 ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002791
2792 match_str = android::base::StringPrintf(R"(\n--->%s.*\n)", format_pointer(ptr).c_str());
2793 ASSERT_MATCH(result, match_str);
2794}
Christopher Ferris2038cc72021-09-15 03:57:10 +00002795
2796static constexpr uint32_t kDexData[] = {
2797 0x0a786564, 0x00383330, 0xc98b3ab8, 0xf3749d94, 0xaecca4d8, 0xffc7b09a, 0xdca9ca7f, 0x5be5deab,
2798 0x00000220, 0x00000070, 0x12345678, 0x00000000, 0x00000000, 0x0000018c, 0x00000008, 0x00000070,
2799 0x00000004, 0x00000090, 0x00000002, 0x000000a0, 0x00000000, 0x00000000, 0x00000003, 0x000000b8,
2800 0x00000001, 0x000000d0, 0x00000130, 0x000000f0, 0x00000122, 0x0000012a, 0x00000132, 0x00000146,
2801 0x00000151, 0x00000154, 0x00000158, 0x0000016d, 0x00000001, 0x00000002, 0x00000004, 0x00000006,
2802 0x00000004, 0x00000002, 0x00000000, 0x00000005, 0x00000002, 0x0000011c, 0x00000000, 0x00000000,
2803 0x00010000, 0x00000007, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000,
2804 0x00000003, 0x00000000, 0x0000017e, 0x00000000, 0x00010001, 0x00000001, 0x00000173, 0x00000004,
2805 0x00021070, 0x000e0000, 0x00010001, 0x00000000, 0x00000178, 0x00000001, 0x0000000e, 0x00000001,
2806 0x3c060003, 0x74696e69, 0x4c06003e, 0x6e69614d, 0x4c12003b, 0x6176616a, 0x6e616c2f, 0x624f2f67,
2807 0x7463656a, 0x4d09003b, 0x2e6e6961, 0x6176616a, 0x00560100, 0x004c5602, 0x6a4c5b13, 0x2f617661,
2808 0x676e616c, 0x7274532f, 0x3b676e69, 0x616d0400, 0x01006e69, 0x000e0700, 0x07000103, 0x0000000e,
2809 0x81000002, 0x01f00480, 0x02880901, 0x0000000c, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
2810 0x00000008, 0x00000070, 0x00000002, 0x00000004, 0x00000090, 0x00000003, 0x00000002, 0x000000a0,
2811 0x00000005, 0x00000003, 0x000000b8, 0x00000006, 0x00000001, 0x000000d0, 0x00002001, 0x00000002,
2812 0x000000f0, 0x00001001, 0x00000001, 0x0000011c, 0x00002002, 0x00000008, 0x00000122, 0x00002003,
2813 0x00000002, 0x00000173, 0x00002000, 0x00000001, 0x0000017e, 0x00001000, 0x00000001, 0x0000018c,
2814};
2815
2816TEST_F(CrasherTest, verify_dex_pc_with_function_name) {
2817 StartProcess([]() {
2818 TemporaryDir td;
2819 std::string tmp_so_name;
2820 if (!CopySharedLibrary(td.path, &tmp_so_name)) {
2821 _exit(1);
2822 }
2823
2824 // In order to cause libunwindstack to look for this __dex_debug_descriptor
2825 // move the library to which has a basename of libart.so.
2826 std::string art_so_name = android::base::Dirname(tmp_so_name) + "/libart.so";
2827 ASSERT_EQ(0, rename(tmp_so_name.c_str(), art_so_name.c_str()));
2828 void* handle = dlopen(art_so_name.c_str(), RTLD_NOW | RTLD_LOCAL);
2829 if (handle == nullptr) {
2830 _exit(1);
2831 }
2832
2833 void* ptr =
2834 mmap(nullptr, sizeof(kDexData), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2835 ASSERT_TRUE(ptr != MAP_FAILED);
2836 memcpy(ptr, kDexData, sizeof(kDexData));
2837 prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, sizeof(kDexData), "dex");
2838
2839 JITCodeEntry dex_entry = {.symfile_addr = reinterpret_cast<uintptr_t>(ptr),
2840 .symfile_size = sizeof(kDexData)};
2841
2842 JITDescriptor* dex_debug =
2843 reinterpret_cast<JITDescriptor*>(dlsym(handle, "__dex_debug_descriptor"));
2844 ASSERT_TRUE(dex_debug != nullptr);
2845 dex_debug->version = 1;
2846 dex_debug->action_flag = 0;
2847 dex_debug->relevant_entry = 0;
2848 dex_debug->first_entry = reinterpret_cast<uintptr_t>(&dex_entry);
2849
2850 // This sets the magic dex pc value for register 0, using the value
2851 // of register 1 + 0x102.
2852 asm(".cfi_escape "
2853 "0x16 /* DW_CFA_val_expression */, 0, 0x0a /* size */,"
2854 "0x0c /* DW_OP_const4u */, 0x44, 0x45, 0x58, 0x31, /* magic = 'DEX1' */"
2855 "0x13 /* DW_OP_drop */,"
2856 "0x92 /* DW_OP_bregx */, 1, 0x82, 0x02 /* 2-byte SLEB128 */");
2857
2858 // For each different architecture, set register one to the dex ptr mmap
2859 // created above. Then do a nullptr dereference to force a crash.
2860#if defined(__arm__)
2861 asm volatile(
2862 "mov r1, %[base]\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002863 "mov r2, #0\n"
2864 "str r2, [r2]\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002865 : [base] "+r"(ptr)
2866 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002867 : "r1", "r2", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002868#elif defined(__aarch64__)
2869 asm volatile(
2870 "mov x1, %[base]\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002871 "mov x2, #0\n"
2872 "str xzr, [x2]\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002873 : [base] "+r"(ptr)
2874 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002875 : "x1", "x2", "memory");
2876#elif defined(__riscv)
2877 // TODO: x1 is ra (the link register) on riscv64, so this might have
2878 // unintended consequences, but we'll need to change the .cfi_escape if so.
2879 asm volatile(
2880 "mv x1, %[base]\n"
2881 "sw zero, 0(zero)\n"
2882 : [base] "+r"(ptr)
2883 :
2884 : "x1", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002885#elif defined(__i386__)
2886 asm volatile(
2887 "mov %[base], %%ecx\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002888 "movl $0, 0\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002889 : [base] "+r"(ptr)
2890 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002891 : "ecx", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002892#elif defined(__x86_64__)
2893 asm volatile(
2894 "mov %[base], %%rdx\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002895 "movq $0, 0\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002896 : [base] "+r"(ptr)
2897 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002898 : "rdx", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002899#else
2900#error "Unsupported architecture"
2901#endif
2902 _exit(0);
2903 });
2904
2905 unique_fd output_fd;
2906 StartIntercept(&output_fd);
2907 FinishCrasher();
2908 AssertDeath(SIGSEGV);
2909
2910 int intercept_result;
2911 FinishIntercept(&intercept_result);
2912 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2913
2914 std::string result;
2915 ConsumeFd(std::move(output_fd), &result);
2916
2917 // Verify the process crashed properly.
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002918 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0*)");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002919
2920 // Now verify that the dex_pc frame includes a proper function name.
2921 ASSERT_MATCH(result, R"( \[anon:dex\] \(Main\.\<init\>\+2)");
2922}
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00002923
2924static std::string format_map_pointer(uintptr_t ptr) {
2925#if defined(__LP64__)
2926 return android::base::StringPrintf("%08x'%08x", static_cast<uint32_t>(ptr >> 32),
2927 static_cast<uint32_t>(ptr & 0xffffffff));
2928#else
2929 return android::base::StringPrintf("%08x", ptr);
2930#endif
2931}
2932
2933// Verify that map data is properly formatted.
2934TEST_F(CrasherTest, verify_map_format) {
2935 // Create multiple maps to make sure that the map data is formatted properly.
2936 void* none_map = mmap(nullptr, getpagesize(), 0, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2937 ASSERT_NE(MAP_FAILED, none_map);
2938 void* r_map = mmap(nullptr, getpagesize(), PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2939 ASSERT_NE(MAP_FAILED, r_map);
2940 void* w_map = mmap(nullptr, getpagesize(), PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2941 ASSERT_NE(MAP_FAILED, w_map);
2942 void* x_map = mmap(nullptr, getpagesize(), PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2943 ASSERT_NE(MAP_FAILED, x_map);
2944
2945 TemporaryFile tf;
2946 ASSERT_EQ(0x2000, lseek(tf.fd, 0x2000, SEEK_SET));
2947 char c = 'f';
2948 ASSERT_EQ(1, write(tf.fd, &c, 1));
2949 ASSERT_EQ(0x5000, lseek(tf.fd, 0x5000, SEEK_SET));
2950 ASSERT_EQ(1, write(tf.fd, &c, 1));
2951 ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
2952 void* file_map = mmap(nullptr, 0x3001, PROT_READ, MAP_PRIVATE, tf.fd, 0x2000);
2953 ASSERT_NE(MAP_FAILED, file_map);
2954
2955 StartProcess([]() { abort(); });
2956
2957 ASSERT_EQ(0, munmap(none_map, getpagesize()));
2958 ASSERT_EQ(0, munmap(r_map, getpagesize()));
2959 ASSERT_EQ(0, munmap(w_map, getpagesize()));
2960 ASSERT_EQ(0, munmap(x_map, getpagesize()));
2961 ASSERT_EQ(0, munmap(file_map, 0x3001));
2962
2963 unique_fd output_fd;
2964 StartIntercept(&output_fd);
2965 FinishCrasher();
2966 AssertDeath(SIGABRT);
2967 int intercept_result;
2968 FinishIntercept(&intercept_result);
2969
2970 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2971
2972 std::string result;
2973 ConsumeFd(std::move(output_fd), &result);
2974
2975 std::string match_str;
2976 // Verify none.
2977 match_str = android::base::StringPrintf(
2978 " %s-%s --- 0 1000\\n",
2979 format_map_pointer(reinterpret_cast<uintptr_t>(none_map)).c_str(),
2980 format_map_pointer(reinterpret_cast<uintptr_t>(none_map) + getpagesize() - 1).c_str());
2981 ASSERT_MATCH(result, match_str);
2982
2983 // Verify read-only.
2984 match_str = android::base::StringPrintf(
2985 " %s-%s r-- 0 1000\\n",
2986 format_map_pointer(reinterpret_cast<uintptr_t>(r_map)).c_str(),
2987 format_map_pointer(reinterpret_cast<uintptr_t>(r_map) + getpagesize() - 1).c_str());
2988 ASSERT_MATCH(result, match_str);
2989
2990 // Verify write-only.
2991 match_str = android::base::StringPrintf(
2992 " %s-%s -w- 0 1000\\n",
2993 format_map_pointer(reinterpret_cast<uintptr_t>(w_map)).c_str(),
2994 format_map_pointer(reinterpret_cast<uintptr_t>(w_map) + getpagesize() - 1).c_str());
2995 ASSERT_MATCH(result, match_str);
2996
2997 // Verify exec-only.
2998 match_str = android::base::StringPrintf(
2999 " %s-%s --x 0 1000\\n",
3000 format_map_pointer(reinterpret_cast<uintptr_t>(x_map)).c_str(),
3001 format_map_pointer(reinterpret_cast<uintptr_t>(x_map) + getpagesize() - 1).c_str());
3002 ASSERT_MATCH(result, match_str);
3003
3004 // Verify file map with non-zero offset and a name.
3005 match_str = android::base::StringPrintf(
3006 " %s-%s r-- 2000 4000 %s\\n",
3007 format_map_pointer(reinterpret_cast<uintptr_t>(file_map)).c_str(),
3008 format_map_pointer(reinterpret_cast<uintptr_t>(file_map) + 0x3fff).c_str(), tf.path);
3009 ASSERT_MATCH(result, match_str);
3010}
3011
3012// Verify that the tombstone map data is correct.
3013TEST_F(CrasherTest, verify_header) {
3014 StartProcess([]() { abort(); });
3015
3016 unique_fd output_fd;
3017 StartIntercept(&output_fd);
3018 FinishCrasher();
3019 AssertDeath(SIGABRT);
3020 int intercept_result;
3021 FinishIntercept(&intercept_result);
3022
3023 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3024
3025 std::string result;
3026 ConsumeFd(std::move(output_fd), &result);
3027
3028 std::string match_str = android::base::StringPrintf(
3029 "Build fingerprint: '%s'\\nRevision: '%s'\\n",
3030 android::base::GetProperty("ro.build.fingerprint", "unknown").c_str(),
3031 android::base::GetProperty("ro.revision", "unknown").c_str());
3032 match_str += android::base::StringPrintf("ABI: '%s'\n", ABI_STRING);
3033 ASSERT_MATCH(result, match_str);
3034}
3035
3036// Verify that the thread header is formatted properly.
3037TEST_F(CrasherTest, verify_thread_header) {
3038 void* shared_map =
3039 mmap(nullptr, sizeof(pid_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
3040 ASSERT_NE(MAP_FAILED, shared_map);
3041 memset(shared_map, 0, sizeof(pid_t));
3042
3043 StartProcess([&shared_map]() {
3044 std::atomic_bool tid_written;
3045 std::thread thread([&tid_written, &shared_map]() {
3046 pid_t tid = gettid();
3047 memcpy(shared_map, &tid, sizeof(pid_t));
3048 tid_written = true;
3049 volatile bool done = false;
3050 while (!done)
3051 ;
3052 });
3053 thread.detach();
3054 while (!tid_written.load(std::memory_order_acquire))
3055 ;
3056 abort();
3057 });
3058
3059 pid_t primary_pid = crasher_pid;
3060
3061 unique_fd output_fd;
3062 StartIntercept(&output_fd);
3063 FinishCrasher();
3064 AssertDeath(SIGABRT);
3065 int intercept_result;
3066 FinishIntercept(&intercept_result);
3067 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3068
3069 // Read the tid data out.
3070 pid_t tid;
3071 memcpy(&tid, shared_map, sizeof(pid_t));
3072 ASSERT_NE(0, tid);
3073
3074 ASSERT_EQ(0, munmap(shared_map, sizeof(pid_t)));
3075
3076 std::string result;
3077 ConsumeFd(std::move(output_fd), &result);
3078
3079 // Verify that there are two headers, one where the tid is "primary_pid"
3080 // and the other where the tid is "tid".
3081 std::string match_str = android::base::StringPrintf("pid: %d, tid: %d, name: .* >>> .* <<<\\n",
3082 primary_pid, primary_pid);
3083 ASSERT_MATCH(result, match_str);
3084
3085 match_str =
3086 android::base::StringPrintf("pid: %d, tid: %d, name: .* >>> .* <<<\\n", primary_pid, tid);
3087 ASSERT_MATCH(result, match_str);
3088}
3089
3090// Verify that there is a BuildID present in the map section and set properly.
3091TEST_F(CrasherTest, verify_build_id) {
3092 StartProcess([]() { abort(); });
3093
3094 unique_fd output_fd;
3095 StartIntercept(&output_fd);
3096 FinishCrasher();
3097 AssertDeath(SIGABRT);
3098 int intercept_result;
3099 FinishIntercept(&intercept_result);
3100 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3101
3102 std::string result;
3103 ConsumeFd(std::move(output_fd), &result);
3104
3105 // Find every /system or /apex lib and verify the BuildID is displayed
3106 // properly.
3107 bool found_valid_elf = false;
3108 std::smatch match;
3109 std::regex build_id_regex(R"( ((/system/|/apex/)\S+) \(BuildId: ([^\)]+)\))");
3110 for (std::string prev_file; std::regex_search(result, match, build_id_regex);
3111 result = match.suffix()) {
3112 if (prev_file == match[1]) {
3113 // Already checked this file.
3114 continue;
3115 }
3116
3117 prev_file = match[1];
Christopher Ferris15038902023-11-10 00:05:49 -08003118 auto elf_memory = unwindstack::Memory::CreateFileMemory(prev_file, 0);
3119 unwindstack::Elf elf(elf_memory);
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00003120 if (!elf.Init() || !elf.valid()) {
3121 // Skipping invalid elf files.
3122 continue;
3123 }
3124 ASSERT_EQ(match[3], elf.GetPrintableBuildID());
3125
3126 found_valid_elf = true;
3127 }
3128 ASSERT_TRUE(found_valid_elf) << "Did not find any elf files with valid BuildIDs to check.";
3129}
Christopher Ferrisbda10642023-04-24 18:14:53 -07003130
3131const char kLogMessage[] = "Should not see this log message.";
3132
3133// Verify that the logd process does not read the log.
3134TEST_F(CrasherTest, logd_skips_reading_logs) {
3135 StartProcess([]() {
3136 pthread_setname_np(pthread_self(), "logd");
3137 LOG(INFO) << kLogMessage;
3138 abort();
3139 });
3140
3141 unique_fd output_fd;
3142 StartIntercept(&output_fd);
3143 FinishCrasher();
3144 AssertDeath(SIGABRT);
3145 int intercept_result;
3146 FinishIntercept(&intercept_result);
3147 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3148
3149 std::string result;
3150 ConsumeFd(std::move(output_fd), &result);
3151 // logd should not contain our log message.
3152 ASSERT_NOT_MATCH(result, kLogMessage);
3153}
3154
3155// Verify that the logd process does not read the log when the non-main
3156// thread crashes.
3157TEST_F(CrasherTest, logd_skips_reading_logs_not_main_thread) {
3158 StartProcess([]() {
3159 pthread_setname_np(pthread_self(), "logd");
3160 LOG(INFO) << kLogMessage;
3161
3162 std::thread thread([]() {
3163 pthread_setname_np(pthread_self(), "not_logd_thread");
3164 // Raise the signal on the side thread.
3165 raise_debugger_signal(kDebuggerdTombstone);
3166 });
3167 thread.join();
3168 _exit(0);
3169 });
3170
3171 unique_fd output_fd;
3172 StartIntercept(&output_fd, kDebuggerdTombstone);
3173 FinishCrasher();
3174 AssertDeath(0);
3175
3176 int intercept_result;
3177 FinishIntercept(&intercept_result);
3178 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3179
3180 std::string result;
3181 ConsumeFd(std::move(output_fd), &result);
3182 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
3183 ASSERT_NOT_MATCH(result, kLogMessage);
3184}
Christopher Ferris98d62422023-05-24 20:01:10 +00003185
3186// Disable this test since there is a high liklihood that this would
3187// be flaky since it requires 500 messages being in the log.
3188TEST_F(CrasherTest, DISABLED_max_log_messages) {
3189 StartProcess([]() {
3190 for (size_t i = 0; i < 600; i++) {
3191 LOG(INFO) << "Message number " << i;
3192 }
3193 abort();
3194 });
3195
3196 unique_fd output_fd;
3197 StartIntercept(&output_fd);
3198 FinishCrasher();
3199 AssertDeath(SIGABRT);
3200 int intercept_result;
3201 FinishIntercept(&intercept_result);
3202 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3203
3204 std::string result;
3205 ConsumeFd(std::move(output_fd), &result);
3206 ASSERT_NOT_MATCH(result, "Message number 99");
3207 ASSERT_MATCH(result, "Message number 100");
3208 ASSERT_MATCH(result, "Message number 599");
3209}
3210
3211TEST_F(CrasherTest, log_with_newline) {
3212 StartProcess([]() {
3213 LOG(INFO) << "This line has a newline.\nThis is on the next line.";
3214 abort();
3215 });
3216
3217 unique_fd output_fd;
3218 StartIntercept(&output_fd);
3219 FinishCrasher();
3220 AssertDeath(SIGABRT);
3221 int intercept_result;
3222 FinishIntercept(&intercept_result);
3223 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3224
3225 std::string result;
3226 ConsumeFd(std::move(output_fd), &result);
3227 ASSERT_MATCH(result, ":\\s*This line has a newline.");
3228 ASSERT_MATCH(result, ":\\s*This is on the next line.");
3229}