blob: 08619b980c33560ed5ea25dbf19a0f1d213accd5 [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 Ferrisdf5ae062024-08-07 20:31:50 +000021#include <inttypes.h>
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +000022#include <linux/prctl.h>
Elliott Hughes03b283a2021-01-15 11:34:26 -080023#include <malloc.h>
Christopher Ferrisbda10642023-04-24 18:14:53 -070024#include <pthread.h>
Florian Mayere6462f92024-02-28 11:12:11 -080025#include <setjmp.h>
Josh Gaocdea7502017-11-01 15:00:40 -070026#include <stdlib.h>
Josh Gao502cfd22017-02-17 01:39:15 -080027#include <sys/capability.h>
Peter Collingbournefe8997a2020-07-20 15:08:52 -070028#include <sys/mman.h>
Josh Gaofca7ca32017-01-23 12:05:35 -080029#include <sys/prctl.h>
Josh Gaofd13bf02017-08-18 15:37:26 -070030#include <sys/ptrace.h>
Josh Gao70adac62018-02-22 11:38:33 -080031#include <sys/resource.h>
Dan Albertc38057a2017-10-11 11:35:40 -070032#include <sys/syscall.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070033#include <sys/types.h>
Josh Gaofd13bf02017-08-18 15:37:26 -070034#include <unistd.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070035
36#include <chrono>
37#include <regex>
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +000038#include <set>
Christopher Ferrisfe751c52021-04-16 09:40:40 -070039#include <string>
Josh Gaocbe70cb2016-10-18 18:17:52 -070040#include <thread>
41
Florian Mayer920d95b2024-02-14 12:57:09 -080042#include <android/crash_detail.h>
Christopher Ferris22035cc2023-01-31 17:50:22 -080043#include <android/dlext.h>
Josh Gaobf06a402018-08-27 16:34:01 -070044#include <android/fdsan.h>
Josh Gao502cfd22017-02-17 01:39:15 -080045#include <android/set_abort_message.h>
Mitch Phillips7168a212021-03-09 16:53:23 -080046#include <bionic/malloc.h>
Peter Collingbournef8622522020-04-07 14:07:32 -070047#include <bionic/mte.h>
Josh Gaoa48b41b2019-12-13 14:11:04 -080048#include <bionic/reserved_signals.h>
Josh Gao502cfd22017-02-17 01:39:15 -080049
Josh Gao5f87bbd2019-01-09 17:01:49 -080050#include <android-base/cmsg.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070051#include <android-base/file.h>
52#include <android-base/logging.h>
Josh Gao2e7b8e22017-05-04 17:12:57 -070053#include <android-base/macros.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070054#include <android-base/parseint.h>
55#include <android-base/properties.h>
Josh Gao2b22ae12018-09-12 14:51:03 -070056#include <android-base/stringprintf.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070057#include <android-base/strings.h>
Josh Gao30171a82017-04-27 19:48:44 -070058#include <android-base/test_utils.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070059#include <android-base/unique_fd.h>
60#include <cutils/sockets.h>
Mitch Phillips78f06702021-06-01 14:35:43 -070061#include <gmock/gmock.h>
Josh Gaocbe70cb2016-10-18 18:17:52 -070062#include <gtest/gtest.h>
63
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +000064#include <unwindstack/Elf.h>
65#include <unwindstack/Memory.h>
66
Josh Gaoe04ca272018-01-16 15:38:17 -080067#include <libminijail.h>
68#include <scoped_minijail.h>
69
Christopher Ferris2038cc72021-09-15 03:57:10 +000070#include "crash_test.h"
Narayan Kamath2d377cd2017-05-10 10:58:59 +010071#include "debuggerd/handler.h"
Mitch Phillips18ce5422023-01-19 14:23:49 -080072#include "gtest/gtest.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
Christopher Ferrisdf5ae062024-08-07 20:31:50 +000089constexpr size_t kTagGranuleSize = 16;
Elliott Hughese4781d52021-03-17 09:15:15 -070090constexpr char kWaitForDebuggerKey[] = "debug.debuggerd.wait_for_debugger";
Josh Gaocbe70cb2016-10-18 18:17:52 -070091
92#define TIMEOUT(seconds, expr) \
93 [&]() { \
94 struct sigaction old_sigaction; \
95 struct sigaction new_sigaction = {}; \
96 new_sigaction.sa_handler = [](int) {}; \
Christopher Ferris16a7bc22022-01-31 13:08:54 -080097 if (sigaction(SIGALRM, &new_sigaction, &old_sigaction) != 0) { \
Josh Gaocbe70cb2016-10-18 18:17:52 -070098 err(1, "sigaction failed"); \
99 } \
Mattias Simonsson38ab0452023-11-08 12:02:46 +0000100 alarm(seconds * android::base::HwTimeoutMultiplier()); \
Josh Gaocbe70cb2016-10-18 18:17:52 -0700101 auto value = expr; \
102 int saved_errno = errno; \
103 if (sigaction(SIGALRM, &old_sigaction, nullptr) != 0) { \
104 err(1, "sigaction failed"); \
105 } \
106 alarm(0); \
107 errno = saved_errno; \
108 return value; \
109 }()
110
Chih-Hung Hsieh3249b3a2018-05-11 16:01:21 -0700111// Backtrace frame dump could contain:
112// #01 pc 0001cded /data/tmp/debuggerd_test32 (raise_debugger_signal+80)
113// or
114// #01 pc 00022a09 /data/tmp/debuggerd_test32 (offset 0x12000) (raise_debugger_signal+80)
Josh Gaoe04ca272018-01-16 15:38:17 -0800115#define ASSERT_BACKTRACE_FRAME(result, frame_name) \
Chih-Hung Hsieh3249b3a2018-05-11 16:01:21 -0700116 ASSERT_MATCH(result, \
117 R"(#\d\d pc [0-9a-f]+\s+ \S+ (\(offset 0x[0-9a-f]+\) )?\()" frame_name R"(\+)");
Jaesung Chung58778e12017-06-15 18:20:34 +0900118
Narayan Kamatha73df602017-05-24 15:07:25 +0100119static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, unique_fd* output_fd,
Christopher Ferrisb92b52c2023-10-16 19:14:28 -0700120 InterceptResponse* response, DebuggerdDumpType intercept_type) {
Josh Gao460b3362017-03-30 16:40:47 -0700121 intercept_fd->reset(socket_local_client(kTombstonedInterceptSocketName,
122 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
123 if (intercept_fd->get() == -1) {
124 FAIL() << "failed to contact tombstoned: " << strerror(errno);
125 }
126
Nick Desaulniers67d52aa2019-10-07 23:28:15 -0700127 InterceptRequest req = {
128 .dump_type = intercept_type,
129 .pid = target_pid,
130 };
Josh Gao460b3362017-03-30 16:40:47 -0700131
132 unique_fd output_pipe_write;
133 if (!Pipe(output_fd, &output_pipe_write)) {
134 FAIL() << "failed to create output pipe: " << strerror(errno);
135 }
136
137 std::string pipe_size_str;
138 int pipe_buffer_size;
139 if (!android::base::ReadFileToString("/proc/sys/fs/pipe-max-size", &pipe_size_str)) {
140 FAIL() << "failed to read /proc/sys/fs/pipe-max-size: " << strerror(errno);
141 }
142
143 pipe_size_str = android::base::Trim(pipe_size_str);
144
145 if (!android::base::ParseInt(pipe_size_str.c_str(), &pipe_buffer_size, 0)) {
146 FAIL() << "failed to parse pipe max size";
147 }
148
149 if (fcntl(output_fd->get(), F_SETPIPE_SZ, pipe_buffer_size) != pipe_buffer_size) {
150 FAIL() << "failed to set pipe size: " << strerror(errno);
151 }
152
Josh Gao5675f3c2017-06-01 12:19:53 -0700153 ASSERT_GE(pipe_buffer_size, 1024 * 1024);
154
Josh Gao5f87bbd2019-01-09 17:01:49 -0800155 ssize_t rc = SendFileDescriptors(intercept_fd->get(), &req, sizeof(req), output_pipe_write.get());
156 output_pipe_write.reset();
157 if (rc != sizeof(req)) {
Josh Gao460b3362017-03-30 16:40:47 -0700158 FAIL() << "failed to send output fd to tombstoned: " << strerror(errno);
159 }
160
Christopher Ferrisb92b52c2023-10-16 19:14:28 -0700161 rc = TEMP_FAILURE_RETRY(read(intercept_fd->get(), response, sizeof(*response)));
Josh Gao460b3362017-03-30 16:40:47 -0700162 if (rc == -1) {
163 FAIL() << "failed to read response from tombstoned: " << strerror(errno);
164 } else if (rc == 0) {
165 FAIL() << "failed to read response from tombstoned (EOF)";
Christopher Ferrisb92b52c2023-10-16 19:14:28 -0700166 } else if (rc != sizeof(*response)) {
167 FAIL() << "received packet of unexpected length from tombstoned: expected " << sizeof(*response)
Josh Gao460b3362017-03-30 16:40:47 -0700168 << ", received " << rc;
169 }
Josh Gao460b3362017-03-30 16:40:47 -0700170}
171
Elliott Hughesd13ea522022-01-13 09:20:26 -0800172static bool pac_supported() {
173#if defined(__aarch64__)
174 return getauxval(AT_HWCAP) & HWCAP_PACA;
175#else
176 return false;
177#endif
178}
179
Josh Gaocbe70cb2016-10-18 18:17:52 -0700180class CrasherTest : public ::testing::Test {
181 public:
182 pid_t crasher_pid = -1;
Elliott Hughese4781d52021-03-17 09:15:15 -0700183 bool previous_wait_for_debugger;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700184 unique_fd crasher_pipe;
185 unique_fd intercept_fd;
186
187 CrasherTest();
188 ~CrasherTest();
189
Narayan Kamatha73df602017-05-24 15:07:25 +0100190 void StartIntercept(unique_fd* output_fd, DebuggerdDumpType intercept_type = kDebuggerdTombstone);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700191
192 // Returns -1 if we fail to read a response from tombstoned, otherwise the received return code.
193 void FinishIntercept(int* result);
194
Josh Gao2e7b8e22017-05-04 17:12:57 -0700195 void StartProcess(std::function<void()> function, std::function<pid_t()> forker = fork);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700196 void StartCrasher(const std::string& crash_type);
197 void FinishCrasher();
198 void AssertDeath(int signo);
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700199
200 static void Trap(void* ptr);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700201};
202
203CrasherTest::CrasherTest() {
Elliott Hughese4781d52021-03-17 09:15:15 -0700204 previous_wait_for_debugger = android::base::GetBoolProperty(kWaitForDebuggerKey, false);
205 android::base::SetProperty(kWaitForDebuggerKey, "0");
206
207 // Clear the old property too, just in case someone's been using it
208 // on this device. (We only document the new name, but we still support
209 // the old name so we don't break anyone's existing setups.)
210 android::base::SetProperty("debug.debuggerd.wait_for_gdb", "0");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700211}
212
213CrasherTest::~CrasherTest() {
214 if (crasher_pid != -1) {
215 kill(crasher_pid, SIGKILL);
216 int status;
Christopher Ferris172b0a02019-09-18 17:48:30 -0700217 TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, WUNTRACED));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700218 }
219
Elliott Hughese4781d52021-03-17 09:15:15 -0700220 android::base::SetProperty(kWaitForDebuggerKey, previous_wait_for_debugger ? "1" : "0");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700221}
222
Narayan Kamatha73df602017-05-24 15:07:25 +0100223void CrasherTest::StartIntercept(unique_fd* output_fd, DebuggerdDumpType intercept_type) {
Josh Gaocbe70cb2016-10-18 18:17:52 -0700224 if (crasher_pid == -1) {
225 FAIL() << "crasher hasn't been started";
226 }
227
Christopher Ferrisb92b52c2023-10-16 19:14:28 -0700228 InterceptResponse response = {};
229 tombstoned_intercept(crasher_pid, &this->intercept_fd, output_fd, &response, intercept_type);
230 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
231 << "Error message: " << response.error_message;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700232}
233
234void CrasherTest::FinishIntercept(int* result) {
235 InterceptResponse response;
236
Christopher Ferris11555f02019-09-20 14:18:55 -0700237 ssize_t rc = TIMEOUT(30, read(intercept_fd.get(), &response, sizeof(response)));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700238 if (rc == -1) {
239 FAIL() << "failed to read response from tombstoned: " << strerror(errno);
240 } else if (rc == 0) {
241 *result = -1;
242 } else if (rc != sizeof(response)) {
243 FAIL() << "received packet of unexpected length from tombstoned: expected " << sizeof(response)
244 << ", received " << rc;
245 } else {
Josh Gao460b3362017-03-30 16:40:47 -0700246 *result = response.status == InterceptStatus::kStarted ? 1 : 0;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700247 }
248}
249
Josh Gao2e7b8e22017-05-04 17:12:57 -0700250void CrasherTest::StartProcess(std::function<void()> function, std::function<pid_t()> forker) {
Josh Gaofca7ca32017-01-23 12:05:35 -0800251 unique_fd read_pipe;
Josh Gaocbe70cb2016-10-18 18:17:52 -0700252 unique_fd crasher_read_pipe;
253 if (!Pipe(&crasher_read_pipe, &crasher_pipe)) {
254 FAIL() << "failed to create pipe: " << strerror(errno);
255 }
256
Josh Gao2e7b8e22017-05-04 17:12:57 -0700257 crasher_pid = forker();
Josh Gaocbe70cb2016-10-18 18:17:52 -0700258 if (crasher_pid == -1) {
259 FAIL() << "fork failed: " << strerror(errno);
260 } else if (crasher_pid == 0) {
Josh Gao502cfd22017-02-17 01:39:15 -0800261 char dummy;
262 crasher_pipe.reset();
263 TEMP_FAILURE_RETRY(read(crasher_read_pipe.get(), &dummy, 1));
Josh Gaofca7ca32017-01-23 12:05:35 -0800264 function();
265 _exit(0);
266 }
267}
268
Josh Gaocbe70cb2016-10-18 18:17:52 -0700269void CrasherTest::FinishCrasher() {
270 if (crasher_pipe == -1) {
271 FAIL() << "crasher pipe uninitialized";
272 }
273
Christopher Ferris172b0a02019-09-18 17:48:30 -0700274 ssize_t rc = TEMP_FAILURE_RETRY(write(crasher_pipe.get(), "\n", 1));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700275 if (rc == -1) {
276 FAIL() << "failed to write to crasher pipe: " << strerror(errno);
277 } else if (rc == 0) {
278 FAIL() << "crasher pipe was closed";
279 }
280}
281
282void CrasherTest::AssertDeath(int signo) {
283 int status;
Christopher Ferris11555f02019-09-20 14:18:55 -0700284 pid_t pid = TIMEOUT(30, waitpid(crasher_pid, &status, 0));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700285 if (pid != crasher_pid) {
Christopher Ferrisafc0ff72019-06-26 15:08:51 -0700286 printf("failed to wait for crasher (expected pid %d, return value %d): %s\n", crasher_pid, pid,
287 strerror(errno));
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700288 sleep(100);
Josh Gaocbe70cb2016-10-18 18:17:52 -0700289 FAIL() << "failed to wait for crasher: " << strerror(errno);
290 }
291
Josh Gaoe06f2a42017-04-27 16:50:38 -0700292 if (signo == 0) {
Christopher Ferris67022562021-04-16 13:30:32 -0700293 ASSERT_TRUE(WIFEXITED(status)) << "Terminated due to unexpected signal " << WTERMSIG(status);
Josh Gaoe06f2a42017-04-27 16:50:38 -0700294 ASSERT_EQ(0, WEXITSTATUS(signo));
295 } else {
296 ASSERT_FALSE(WIFEXITED(status));
297 ASSERT_TRUE(WIFSIGNALED(status)) << "crasher didn't terminate via a signal";
298 ASSERT_EQ(signo, WTERMSIG(status));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700299 }
Josh Gaocbe70cb2016-10-18 18:17:52 -0700300 crasher_pid = -1;
301}
302
303static void ConsumeFd(unique_fd fd, std::string* output) {
Kelvin Zhang786dac32023-06-15 16:23:56 -0700304 ASSERT_TRUE(android::base::ReadFdToString(fd, output));
Josh Gaocbe70cb2016-10-18 18:17:52 -0700305}
306
Mitch Phillips78f06702021-06-01 14:35:43 -0700307class LogcatCollector {
308 public:
309 LogcatCollector() { system("logcat -c"); }
310
311 void Collect(std::string* output) {
312 FILE* cmd_stdout = popen("logcat -d '*:S DEBUG'", "r");
313 ASSERT_NE(cmd_stdout, nullptr);
314 unique_fd tmp_fd(TEMP_FAILURE_RETRY(dup(fileno(cmd_stdout))));
315 ConsumeFd(std::move(tmp_fd), output);
316 pclose(cmd_stdout);
317 }
318};
319
Josh Gaocbe70cb2016-10-18 18:17:52 -0700320TEST_F(CrasherTest, smoke) {
321 int intercept_result;
322 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -0800323 StartProcess([]() {
324 *reinterpret_cast<volatile char*>(0xdead) = '1';
325 });
326
Josh Gaocbe70cb2016-10-18 18:17:52 -0700327 StartIntercept(&output_fd);
328 FinishCrasher();
329 AssertDeath(SIGSEGV);
330 FinishIntercept(&intercept_result);
331
332 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
333
334 std::string result;
335 ConsumeFd(std::move(output_fd), &result);
Christopher Ferris2f77c2a2024-05-07 12:25:31 -0700336 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+dead)");
Peter Collingbourne864f15d2020-09-14 20:27:36 -0700337
338 if (mte_supported()) {
339 // Test that the default TAGGED_ADDR_CTRL value is set.
Peter Collingbourne47d784e2021-11-05 18:40:52 -0700340 ASSERT_MATCH(result, R"(tagged_addr_ctrl: 000000000007fff3)"
341 R"( \(PR_TAGGED_ADDR_ENABLE, PR_MTE_TCF_SYNC, mask 0xfffe\))");
Peter Collingbourne864f15d2020-09-14 20:27:36 -0700342 }
Elliott Hughesd13ea522022-01-13 09:20:26 -0800343
344 if (pac_supported()) {
345 // Test that the default PAC_ENABLED_KEYS value is set.
346 ASSERT_MATCH(result, R"(pac_enabled_keys: 000000000000000f)"
347 R"( \(PR_PAC_APIAKEY, PR_PAC_APIBKEY, PR_PAC_APDAKEY, PR_PAC_APDBKEY\))");
348 }
Josh Gaocbe70cb2016-10-18 18:17:52 -0700349}
350
Peter Collingbournef03af882020-03-20 18:09:00 -0700351TEST_F(CrasherTest, tagged_fault_addr) {
352#if !defined(__aarch64__)
353 GTEST_SKIP() << "Requires aarch64";
354#endif
Florian Mayerb4979292022-04-15 14:35:17 -0700355 // HWASan crashes with SIGABRT on tag mismatch.
356 SKIP_WITH_HWASAN;
Peter Collingbournef03af882020-03-20 18:09:00 -0700357 int intercept_result;
358 unique_fd output_fd;
359 StartProcess([]() {
360 *reinterpret_cast<volatile char*>(0x100000000000dead) = '1';
361 });
362
363 StartIntercept(&output_fd);
364 FinishCrasher();
365 AssertDeath(SIGSEGV);
366 FinishIntercept(&intercept_result);
367
368 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
369
370 std::string result;
371 ConsumeFd(std::move(output_fd), &result);
372
373 // The address can either be tagged (new kernels) or untagged (old kernels).
374 ASSERT_MATCH(
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800375 result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x[01]00000000000dead)");
Peter Collingbournef03af882020-03-20 18:09:00 -0700376}
377
Evgenii Stepanov361455e2022-10-13 16:23:08 -0700378void CrasherTest::Trap(void* ptr) {
379 void (*volatile f)(void*) = nullptr;
380 __asm__ __volatile__("" : : "r"(f) : "memory");
381 f(ptr);
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700382}
383
384TEST_F(CrasherTest, heap_addr_in_register) {
385#if defined(__i386__)
386 GTEST_SKIP() << "architecture does not pass arguments in registers";
387#endif
Florian Mayerb4979292022-04-15 14:35:17 -0700388 // The memory dump in HWASan crashes sadly shows the memory near the registers
389 // in the HWASan dump function, rather the faulting context. This is a known
390 // issue.
391 SKIP_WITH_HWASAN;
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700392 int intercept_result;
393 unique_fd output_fd;
394 StartProcess([]() {
395 // Crash with a heap pointer in the first argument register.
396 Trap(malloc(1));
397 });
398
399 StartIntercept(&output_fd);
400 FinishCrasher();
401 int status;
402 ASSERT_EQ(crasher_pid, TIMEOUT(30, waitpid(crasher_pid, &status, 0)));
403 ASSERT_TRUE(WIFSIGNALED(status)) << "crasher didn't terminate via a signal";
404 // Don't test the signal number because different architectures use different signals for
405 // __builtin_trap().
406 FinishIntercept(&intercept_result);
407
408 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
409
410 std::string result;
411 ConsumeFd(std::move(output_fd), &result);
412
413#if defined(__aarch64__)
Peter Collingbourne0ea08c22021-02-05 14:59:08 -0800414 ASSERT_MATCH(result, "memory near x0 \\(\\[anon:");
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700415#elif defined(__arm__)
Peter Collingbourne0ea08c22021-02-05 14:59:08 -0800416 ASSERT_MATCH(result, "memory near r0 \\(\\[anon:");
haocheng.zy@linux.alibaba.com3f4d0362022-09-10 11:38:19 +0800417#elif defined(__riscv)
418 ASSERT_MATCH(result, "memory near a0 \\(\\[anon:");
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700419#elif defined(__x86_64__)
Peter Collingbourne0ea08c22021-02-05 14:59:08 -0800420 ASSERT_MATCH(result, "memory near rdi \\(\\[anon:");
Peter Collingbourne10e428d2020-07-17 14:49:31 -0700421#else
422 ASSERT_TRUE(false) << "unsupported architecture";
423#endif
424}
425
Peter Collingbournecd278072020-12-21 14:08:38 -0800426#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700427static void SetTagCheckingLevelSync() {
Elliott Hughes03b283a2021-01-15 11:34:26 -0800428 if (mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_SYNC) == 0) {
Peter Collingbournef8622522020-04-07 14:07:32 -0700429 abort();
430 }
431}
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800432
433static void SetTagCheckingLevelAsync() {
434 if (mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_ASYNC) == 0) {
435 abort();
436 }
437}
Peter Collingbournef8622522020-04-07 14:07:32 -0700438#endif
439
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800440struct SizeParamCrasherTest : CrasherTest, testing::WithParamInterface<size_t> {};
441
Peter Collingbourneaa544792021-05-13 13:53:37 -0700442INSTANTIATE_TEST_SUITE_P(Sizes, SizeParamCrasherTest, testing::Values(0, 16, 131072));
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800443
444TEST_P(SizeParamCrasherTest, mte_uaf) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800445#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700446 if (!mte_supported()) {
447 GTEST_SKIP() << "Requires MTE";
448 }
449
Peter Collingbourneaa544792021-05-13 13:53:37 -0700450 // Any UAF on a zero-sized allocation will be out-of-bounds so it won't be reported.
451 if (GetParam() == 0) {
452 return;
453 }
454
Mitch Phillips78f06702021-06-01 14:35:43 -0700455 LogcatCollector logcat_collector;
456
Peter Collingbournef8622522020-04-07 14:07:32 -0700457 int intercept_result;
458 unique_fd output_fd;
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800459 StartProcess([&]() {
Peter Collingbournef8622522020-04-07 14:07:32 -0700460 SetTagCheckingLevelSync();
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800461 volatile int* p = (volatile int*)malloc(GetParam());
Peter Collingbournef8622522020-04-07 14:07:32 -0700462 free((void *)p);
463 p[0] = 42;
464 });
465
466 StartIntercept(&output_fd);
467 FinishCrasher();
468 AssertDeath(SIGSEGV);
469 FinishIntercept(&intercept_result);
470
471 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
472
Mitch Phillips78f06702021-06-01 14:35:43 -0700473 std::vector<std::string> log_sources(2);
474 ConsumeFd(std::move(output_fd), &log_sources[0]);
475 logcat_collector.Collect(&log_sources[1]);
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700476 // Tag dump only available in the tombstone, not logcat.
477 ASSERT_MATCH(log_sources[0], "Memory tags around the fault address");
Peter Collingbournef8622522020-04-07 14:07:32 -0700478
Mitch Phillips78f06702021-06-01 14:35:43 -0700479 for (const auto& result : log_sources) {
480 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
481 ASSERT_MATCH(result, R"(Cause: \[MTE\]: Use After Free, 0 bytes into a )" +
482 std::to_string(GetParam()) + R"(-byte allocation)");
483 ASSERT_MATCH(result, R"(deallocated by thread .*?\n.*#00 pc)");
484 ASSERT_MATCH(result, R"((^|\s)allocated by thread .*?\n.*#00 pc)");
485 }
Peter Collingbournef8622522020-04-07 14:07:32 -0700486#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800487 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournef8622522020-04-07 14:07:32 -0700488#endif
489}
490
Peter Collingbournedc476342021-05-12 15:56:43 -0700491TEST_P(SizeParamCrasherTest, mte_oob_uaf) {
492#if defined(__aarch64__)
493 if (!mte_supported()) {
494 GTEST_SKIP() << "Requires MTE";
495 }
496
497 int intercept_result;
498 unique_fd output_fd;
499 StartProcess([&]() {
500 SetTagCheckingLevelSync();
501 volatile int* p = (volatile int*)malloc(GetParam());
502 free((void *)p);
503 p[-1] = 42;
504 });
505
506 StartIntercept(&output_fd);
507 FinishCrasher();
508 AssertDeath(SIGSEGV);
509 FinishIntercept(&intercept_result);
510
511 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
512
513 std::string result;
514 ConsumeFd(std::move(output_fd), &result);
515
516 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
517 ASSERT_NOT_MATCH(result, R"(Cause: \[MTE\]: Use After Free, 4 bytes left)");
518#else
519 GTEST_SKIP() << "Requires aarch64";
520#endif
521}
522
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800523TEST_P(SizeParamCrasherTest, mte_overflow) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800524#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700525 if (!mte_supported()) {
526 GTEST_SKIP() << "Requires MTE";
527 }
528
Mitch Phillips78f06702021-06-01 14:35:43 -0700529 LogcatCollector logcat_collector;
Peter Collingbournef8622522020-04-07 14:07:32 -0700530 int intercept_result;
531 unique_fd output_fd;
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800532 StartProcess([&]() {
Peter Collingbournef8622522020-04-07 14:07:32 -0700533 SetTagCheckingLevelSync();
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800534 volatile char* p = (volatile char*)malloc(GetParam());
535 p[GetParam()] = 42;
Peter Collingbournef8622522020-04-07 14:07:32 -0700536 });
537
538 StartIntercept(&output_fd);
539 FinishCrasher();
540 AssertDeath(SIGSEGV);
541 FinishIntercept(&intercept_result);
542
543 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
544
Mitch Phillips78f06702021-06-01 14:35:43 -0700545 std::vector<std::string> log_sources(2);
546 ConsumeFd(std::move(output_fd), &log_sources[0]);
547 logcat_collector.Collect(&log_sources[1]);
Peter Collingbournef8622522020-04-07 14:07:32 -0700548
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700549 // Tag dump only in tombstone, not logcat, and tagging is not used for
550 // overflow protection in the scudo secondary (guard pages are used instead).
551 if (GetParam() < 0x10000) {
552 ASSERT_MATCH(log_sources[0], "Memory tags around the fault address");
553 }
554
Mitch Phillips78f06702021-06-01 14:35:43 -0700555 for (const auto& result : log_sources) {
556 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
557 ASSERT_MATCH(result, R"(Cause: \[MTE\]: Buffer Overflow, 0 bytes right of a )" +
558 std::to_string(GetParam()) + R"(-byte allocation)");
559 ASSERT_MATCH(result, R"((^|\s)allocated by thread .*?\n.*#00 pc)");
560 }
Peter Collingbournef8622522020-04-07 14:07:32 -0700561#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800562 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournef8622522020-04-07 14:07:32 -0700563#endif
564}
565
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800566TEST_P(SizeParamCrasherTest, mte_underflow) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800567#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700568 if (!mte_supported()) {
569 GTEST_SKIP() << "Requires MTE";
570 }
571
572 int intercept_result;
573 unique_fd output_fd;
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800574 StartProcess([&]() {
Peter Collingbournef8622522020-04-07 14:07:32 -0700575 SetTagCheckingLevelSync();
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800576 volatile int* p = (volatile int*)malloc(GetParam());
Peter Collingbournef8622522020-04-07 14:07:32 -0700577 p[-1] = 42;
578 });
579
580 StartIntercept(&output_fd);
581 FinishCrasher();
582 AssertDeath(SIGSEGV);
583 FinishIntercept(&intercept_result);
584
585 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
586
587 std::string result;
588 ConsumeFd(std::move(output_fd), &result);
589
590 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 9 \(SEGV_MTESERR\))");
Peter Collingbournebb4b49c2021-01-06 21:02:19 -0800591 ASSERT_MATCH(result, R"(Cause: \[MTE\]: Buffer Underflow, 4 bytes left of a )" +
Peter Collingbourne1a1f7d72021-03-08 16:53:54 -0800592 std::to_string(GetParam()) + R"(-byte allocation)");
Mitch Phillips78f06702021-06-01 14:35:43 -0700593 ASSERT_MATCH(result, R"((^|\s)allocated by thread .*
Peter Collingbournebbe69052020-05-08 10:11:19 -0700594 #00 pc)");
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700595 ASSERT_MATCH(result, "Memory tags around the fault address");
Peter Collingbournef8622522020-04-07 14:07:32 -0700596#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800597 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournef8622522020-04-07 14:07:32 -0700598#endif
599}
600
Florian Mayere6462f92024-02-28 11:12:11 -0800601__attribute__((noinline)) void mte_illegal_setjmp_helper(jmp_buf& jump_buf) {
Florian Mayer1fef1b12024-03-06 16:53:30 -0800602 // This frame is at least 8 bytes for storing and restoring the LR before the
603 // setjmp below. So this can never get an empty stack frame, even if we omit
604 // the frame pointer. So, the SP of this is always less (numerically) than the
605 // calling function frame.
Florian Mayere6462f92024-02-28 11:12:11 -0800606 setjmp(jump_buf);
607}
608
Florian Mayer92164902024-04-10 20:24:56 +0000609TEST_F(CrasherTest, DISABLED_mte_illegal_setjmp) {
Florian Mayere6462f92024-02-28 11:12:11 -0800610 // This setjmp is illegal because it jumps back into a function that already returned.
611 // Quoting man 3 setjmp:
612 // If the function which called setjmp() returns before longjmp() is
613 // called, the behavior is undefined. Some kind of subtle or
614 // unsubtle chaos is sure to result.
615 // https://man7.org/linux/man-pages/man3/longjmp.3.html
616#if defined(__aarch64__)
617 if (!mte_supported()) {
618 GTEST_SKIP() << "Requires MTE";
619 }
620
621 int intercept_result;
622 unique_fd output_fd;
623 StartProcess([&]() {
624 SetTagCheckingLevelSync();
625 jmp_buf jump_buf;
626 mte_illegal_setjmp_helper(jump_buf);
627 longjmp(jump_buf, 1);
628 });
629
630 StartIntercept(&output_fd);
631 FinishCrasher();
632 AssertDeath(SIGABRT);
633 FinishIntercept(&intercept_result);
634
635 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
636
637 std::string result;
638 ConsumeFd(std::move(output_fd), &result);
639
640 // In our test-case, we have a NEGATIVE stack adjustment, which is being
641 // interpreted as unsigned integer, and thus is "too large".
642 // TODO(fmayer): fix the error message for this
643 ASSERT_MATCH(result, R"(memtag_handle_longjmp: stack adjustment too large)");
644#else
645 GTEST_SKIP() << "Requires aarch64";
646#endif
647}
648
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800649TEST_F(CrasherTest, mte_async) {
650#if defined(__aarch64__)
651 if (!mte_supported()) {
652 GTEST_SKIP() << "Requires MTE";
653 }
654
655 int intercept_result;
656 unique_fd output_fd;
657 StartProcess([&]() {
658 SetTagCheckingLevelAsync();
659 volatile int* p = (volatile int*)malloc(16);
660 p[-1] = 42;
661 });
662
663 StartIntercept(&output_fd);
664 FinishCrasher();
665 AssertDeath(SIGSEGV);
666 FinishIntercept(&intercept_result);
667
668 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
669
670 std::string result;
671 ConsumeFd(std::move(output_fd), &result);
672
Peter Collingbourne91e816a2023-03-07 21:24:47 -0800673 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code [89] \(SEGV_MTE[AS]ERR\), fault addr)");
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800674#else
675 GTEST_SKIP() << "Requires aarch64";
676#endif
677}
678
Peter Collingbournef8622522020-04-07 14:07:32 -0700679TEST_F(CrasherTest, mte_multiple_causes) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800680#if defined(__aarch64__)
Peter Collingbournef8622522020-04-07 14:07:32 -0700681 if (!mte_supported()) {
682 GTEST_SKIP() << "Requires MTE";
683 }
684
Mitch Phillips78f06702021-06-01 14:35:43 -0700685 LogcatCollector logcat_collector;
686
Peter Collingbournef8622522020-04-07 14:07:32 -0700687 int intercept_result;
688 unique_fd output_fd;
689 StartProcess([]() {
690 SetTagCheckingLevelSync();
691
692 // Make two allocations with the same tag and close to one another. Check for both properties
693 // with a bounds check -- this relies on the fact that only if the allocations have the same tag
694 // would they be measured as closer than 128 bytes to each other. Otherwise they would be about
695 // (some non-zero value << 56) apart.
696 //
697 // The out-of-bounds access will be considered either an overflow of one or an underflow of the
698 // other.
699 std::set<uintptr_t> allocs;
700 for (int i = 0; i != 4096; ++i) {
701 uintptr_t alloc = reinterpret_cast<uintptr_t>(malloc(16));
702 auto it = allocs.insert(alloc).first;
703 if (it != allocs.begin() && *std::prev(it) + 128 > alloc) {
704 *reinterpret_cast<int*>(*std::prev(it) + 16) = 42;
705 }
706 if (std::next(it) != allocs.end() && alloc + 128 > *std::next(it)) {
707 *reinterpret_cast<int*>(alloc + 16) = 42;
708 }
709 }
710 });
711
712 StartIntercept(&output_fd);
713 FinishCrasher();
714 AssertDeath(SIGSEGV);
715 FinishIntercept(&intercept_result);
716
717 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
718
Mitch Phillips78f06702021-06-01 14:35:43 -0700719 std::vector<std::string> log_sources(2);
720 ConsumeFd(std::move(output_fd), &log_sources[0]);
721 logcat_collector.Collect(&log_sources[1]);
Peter Collingbournef8622522020-04-07 14:07:32 -0700722
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700723 // Tag dump only in the tombstone, not logcat.
724 ASSERT_MATCH(log_sources[0], "Memory tags around the fault address");
725
Mitch Phillips78f06702021-06-01 14:35:43 -0700726 for (const auto& result : log_sources) {
727 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
728 ASSERT_THAT(result, HasSubstr("Note: multiple potential causes for this crash were detected, "
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800729 "listing them in decreasing order of likelihood."));
Mitch Phillips78f06702021-06-01 14:35:43 -0700730 // Adjacent untracked allocations may cause us to see the wrong underflow here (or only
731 // overflows), so we can't match explicitly for an underflow message.
732 ASSERT_MATCH(result,
733 R"(Cause: \[MTE\]: Buffer Overflow, 0 bytes right of a 16-byte allocation)");
734 // Ensure there's at least two allocation traces (one for each cause).
735 ASSERT_MATCH(
736 result,
737 R"((^|\s)allocated by thread .*?\n.*#00 pc(.|\n)*?(^|\s)allocated by thread .*?\n.*#00 pc)");
738 }
Peter Collingbournef8622522020-04-07 14:07:32 -0700739#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800740 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournef8622522020-04-07 14:07:32 -0700741#endif
742}
743
Peter Collingbournecd278072020-12-21 14:08:38 -0800744#if defined(__aarch64__)
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700745static uintptr_t CreateTagMapping() {
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700746 // Some of the MTE tag dump tests assert that there is an inaccessible page to the left and right
747 // of the PROT_MTE page, so map three pages and set the two guard pages to PROT_NONE.
748 size_t page_size = getpagesize();
749 void* mapping = mmap(nullptr, page_size * 3, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
750 uintptr_t mapping_uptr = reinterpret_cast<uintptr_t>(mapping);
751 if (mapping == MAP_FAILED) {
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700752 return 0;
753 }
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700754 mprotect(reinterpret_cast<void*>(mapping_uptr + page_size), page_size,
755 PROT_READ | PROT_WRITE | PROT_MTE);
756 // Stripe the mapping, where even granules get tag '1', and odd granules get tag '0'.
757 for (uintptr_t offset = 0; offset < page_size; offset += 2 * kTagGranuleSize) {
758 uintptr_t tagged_addr = mapping_uptr + page_size + offset + (1ULL << 56);
759 __asm__ __volatile__(".arch_extension mte; stg %0, [%0]" : : "r"(tagged_addr) : "memory");
760 }
761 return mapping_uptr + page_size;
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700762}
763#endif
764
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700765TEST_F(CrasherTest, mte_register_tag_dump) {
Peter Collingbournecd278072020-12-21 14:08:38 -0800766#if defined(__aarch64__)
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700767 if (!mte_supported()) {
768 GTEST_SKIP() << "Requires MTE";
769 }
770
771 int intercept_result;
772 unique_fd output_fd;
773 StartProcess([&]() {
774 SetTagCheckingLevelSync();
775 Trap(reinterpret_cast<void *>(CreateTagMapping()));
776 });
777
778 StartIntercept(&output_fd);
779 FinishCrasher();
Evgenii Stepanov361455e2022-10-13 16:23:08 -0700780 AssertDeath(SIGSEGV);
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700781 FinishIntercept(&intercept_result);
782
783 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
784
785 std::string result;
786 ConsumeFd(std::move(output_fd), &result);
787
788 ASSERT_MATCH(result, R"(memory near x0:
789.*
790.*
791 01.............0 0000000000000000 0000000000000000 ................
792 00.............0)");
793#else
Peter Collingbournecd278072020-12-21 14:08:38 -0800794 GTEST_SKIP() << "Requires aarch64";
Peter Collingbournefe8997a2020-07-20 15:08:52 -0700795#endif
796}
797
Mitch Phillips5ddcea22021-04-19 09:59:17 -0700798TEST_F(CrasherTest, mte_fault_tag_dump_front_truncated) {
799#if defined(__aarch64__)
800 if (!mte_supported()) {
801 GTEST_SKIP() << "Requires MTE";
802 }
803
804 int intercept_result;
805 unique_fd output_fd;
806 StartProcess([&]() {
807 SetTagCheckingLevelSync();
808 volatile char* p = reinterpret_cast<char*>(CreateTagMapping());
809 p[0] = 0; // Untagged pointer, tagged memory.
810 });
811
812 StartIntercept(&output_fd);
813 FinishCrasher();
814 AssertDeath(SIGSEGV);
815 FinishIntercept(&intercept_result);
816
817 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
818
819 std::string result;
820 ConsumeFd(std::move(output_fd), &result);
821
822 ASSERT_MATCH(result, R"(Memory tags around the fault address.*
823\s*=>0x[0-9a-f]+000:\[1\] 0 1 0)");
824#else
825 GTEST_SKIP() << "Requires aarch64";
826#endif
827}
828
829TEST_F(CrasherTest, mte_fault_tag_dump) {
830#if defined(__aarch64__)
831 if (!mte_supported()) {
832 GTEST_SKIP() << "Requires MTE";
833 }
834
835 int intercept_result;
836 unique_fd output_fd;
837 StartProcess([&]() {
838 SetTagCheckingLevelSync();
839 volatile char* p = reinterpret_cast<char*>(CreateTagMapping());
840 p[320] = 0; // Untagged pointer, tagged memory.
841 });
842
843 StartIntercept(&output_fd);
844 FinishCrasher();
845 AssertDeath(SIGSEGV);
846 FinishIntercept(&intercept_result);
847
848 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
849
850 std::string result;
851 ConsumeFd(std::move(output_fd), &result);
852
853 ASSERT_MATCH(result, R"(Memory tags around the fault address.*
854\s*0x[0-9a-f]+: 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
855\s*=>0x[0-9a-f]+: 1 0 1 0 \[1\] 0 1 0 1 0 1 0 1 0 1 0
856\s*0x[0-9a-f]+: 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
857)");
858#else
859 GTEST_SKIP() << "Requires aarch64";
860#endif
861}
862
863TEST_F(CrasherTest, mte_fault_tag_dump_rear_truncated) {
864#if defined(__aarch64__)
865 if (!mte_supported()) {
866 GTEST_SKIP() << "Requires MTE";
867 }
868
869 int intercept_result;
870 unique_fd output_fd;
871 StartProcess([&]() {
872 SetTagCheckingLevelSync();
873 size_t page_size = getpagesize();
874 volatile char* p = reinterpret_cast<char*>(CreateTagMapping());
875 p[page_size - kTagGranuleSize * 2] = 0; // Untagged pointer, tagged memory.
876 });
877
878 StartIntercept(&output_fd);
879 FinishCrasher();
880 AssertDeath(SIGSEGV);
881 FinishIntercept(&intercept_result);
882
883 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
884
885 std::string result;
886 ConsumeFd(std::move(output_fd), &result);
887
888 ASSERT_MATCH(result, R"(Memory tags around the fault address)");
889 ASSERT_MATCH(result,
890 R"(\s*0x[0-9a-f]+: 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
891\s*=>0x[0-9a-f]+: 1 0 1 0 1 0 1 0 1 0 1 0 1 0 \[1\] 0
892
893)"); // Ensure truncation happened and there's a newline after the tag fault.
894#else
895 GTEST_SKIP() << "Requires aarch64";
896#endif
897}
898
Josh Gaocdea7502017-11-01 15:00:40 -0700899TEST_F(CrasherTest, LD_PRELOAD) {
900 int intercept_result;
901 unique_fd output_fd;
902 StartProcess([]() {
903 setenv("LD_PRELOAD", "nonexistent.so", 1);
904 *reinterpret_cast<volatile char*>(0xdead) = '1';
905 });
906
907 StartIntercept(&output_fd);
908 FinishCrasher();
909 AssertDeath(SIGSEGV);
910 FinishIntercept(&intercept_result);
911
912 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
913
914 std::string result;
915 ConsumeFd(std::move(output_fd), &result);
Peter Collingbourne773acaa2021-11-10 16:29:23 -0800916 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+dead)");
Josh Gaocdea7502017-11-01 15:00:40 -0700917}
918
Josh Gaocbe70cb2016-10-18 18:17:52 -0700919TEST_F(CrasherTest, abort) {
920 int intercept_result;
921 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -0800922 StartProcess([]() {
923 abort();
924 });
Josh Gaocbe70cb2016-10-18 18:17:52 -0700925 StartIntercept(&output_fd);
926 FinishCrasher();
927 AssertDeath(SIGABRT);
928 FinishIntercept(&intercept_result);
929
930 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
931
932 std::string result;
933 ConsumeFd(std::move(output_fd), &result);
Andreas Gampe26cbafb2017-06-22 20:14:43 -0700934 ASSERT_BACKTRACE_FRAME(result, "abort");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700935}
936
937TEST_F(CrasherTest, signal) {
938 int intercept_result;
939 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -0800940 StartProcess([]() {
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700941 while (true) {
942 sleep(1);
943 }
Josh Gao502cfd22017-02-17 01:39:15 -0800944 });
Josh Gaocbe70cb2016-10-18 18:17:52 -0700945 StartIntercept(&output_fd);
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700946 FinishCrasher();
Josh Gaocbe70cb2016-10-18 18:17:52 -0700947 ASSERT_EQ(0, kill(crasher_pid, SIGSEGV));
948
949 AssertDeath(SIGSEGV);
950 FinishIntercept(&intercept_result);
951
952 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
953
954 std::string result;
955 ConsumeFd(std::move(output_fd), &result);
Elliott Hughes89722702018-05-02 10:47:00 -0700956 ASSERT_MATCH(
957 result,
958 R"(signal 11 \(SIGSEGV\), code 0 \(SI_USER from pid \d+, uid \d+\), fault addr --------)");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700959 ASSERT_MATCH(result, R"(backtrace:)");
960}
961
962TEST_F(CrasherTest, abort_message) {
963 int intercept_result;
964 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -0800965 StartProcess([]() {
Josh Gao1cc7bd82018-02-13 13:16:17 -0800966 // Arrived at experimentally;
967 // logd truncates at 4062.
968 // strlen("Abort message: ''") is 17.
969 // That's 4045, but we also want a NUL.
970 char buf[4045 + 1];
971 memset(buf, 'x', sizeof(buf));
972 buf[sizeof(buf) - 1] = '\0';
973 android_set_abort_message(buf);
Josh Gao502cfd22017-02-17 01:39:15 -0800974 abort();
975 });
Josh Gaocbe70cb2016-10-18 18:17:52 -0700976 StartIntercept(&output_fd);
977 FinishCrasher();
978 AssertDeath(SIGABRT);
979 FinishIntercept(&intercept_result);
980
981 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
982
983 std::string result;
984 ConsumeFd(std::move(output_fd), &result);
Josh Gao1cc7bd82018-02-13 13:16:17 -0800985 ASSERT_MATCH(result, R"(Abort message: 'x{4045}')");
Josh Gaocbe70cb2016-10-18 18:17:52 -0700986}
987
Florian Mayer5fa66632024-02-07 16:42:23 -0800988static char g_crash_detail_value_changes[] = "crash_detail_value";
989static char g_crash_detail_value[] = "crash_detail_value";
990static char g_crash_detail_value2[] = "crash_detail_value2";
991
992inline crash_detail_t* _Nullable android_register_crash_detail_strs(const char* _Nonnull name,
993 const char* _Nonnull data) {
Florian Mayer920d95b2024-02-14 12:57:09 -0800994 return android_crash_detail_register(name, strlen(name), data, strlen(data));
Florian Mayer5fa66632024-02-07 16:42:23 -0800995}
996
997TEST_F(CrasherTest, crash_detail_single) {
998 int intercept_result;
999 unique_fd output_fd;
1000 StartProcess([]() {
1001 android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value);
1002 abort();
1003 });
1004 StartIntercept(&output_fd);
1005 FinishCrasher();
1006 AssertDeath(SIGABRT);
1007 FinishIntercept(&intercept_result);
1008
1009 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1010
1011 std::string result;
1012 ConsumeFd(std::move(output_fd), &result);
1013 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'crash_detail_value')");
1014}
1015
Florian Mayeraced3aa2024-02-13 13:44:50 -08001016TEST_F(CrasherTest, crash_detail_replace_data) {
1017 int intercept_result;
1018 unique_fd output_fd;
1019 StartProcess([]() {
1020 auto *cd = android_register_crash_detail_strs("CRASH_DETAIL_NAME", "original_data");
Florian Mayer920d95b2024-02-14 12:57:09 -08001021 android_crash_detail_replace_data(cd, "new_data", strlen("new_data"));
Florian Mayeraced3aa2024-02-13 13:44:50 -08001022 abort();
1023 });
1024 StartIntercept(&output_fd);
1025 FinishCrasher();
1026 AssertDeath(SIGABRT);
1027 FinishIntercept(&intercept_result);
1028
1029 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1030
1031 std::string result;
1032 ConsumeFd(std::move(output_fd), &result);
1033 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'new_data')");
1034 // Ensure the old one no longer shows up, i.e. that we actually replaced
1035 // it, not added a new one.
1036 ASSERT_NOT_MATCH(result, R"(CRASH_DETAIL_NAME: 'original_data')");
1037}
1038
1039TEST_F(CrasherTest, crash_detail_replace_name) {
1040 int intercept_result;
1041 unique_fd output_fd;
1042 StartProcess([]() {
1043 auto *cd = android_register_crash_detail_strs("old_name", g_crash_detail_value);
Florian Mayer920d95b2024-02-14 12:57:09 -08001044 android_crash_detail_replace_name(cd, "new_name", strlen("new_name"));
Florian Mayeraced3aa2024-02-13 13:44:50 -08001045 abort();
1046 });
1047 StartIntercept(&output_fd);
1048 FinishCrasher();
1049 AssertDeath(SIGABRT);
1050 FinishIntercept(&intercept_result);
1051
1052 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1053
1054 std::string result;
1055 ConsumeFd(std::move(output_fd), &result);
1056 ASSERT_MATCH(result, R"(new_name: 'crash_detail_value')");
1057 // Ensure the old one no longer shows up, i.e. that we actually replaced
1058 // it, not added a new one.
1059 ASSERT_NOT_MATCH(result, R"(old_name: 'crash_detail_value')");
1060}
1061
Florian Mayer5fa66632024-02-07 16:42:23 -08001062TEST_F(CrasherTest, crash_detail_single_byte_name) {
1063 int intercept_result;
1064 unique_fd output_fd;
1065 StartProcess([]() {
1066 android_register_crash_detail_strs("CRASH_DETAIL_NAME\1", g_crash_detail_value);
1067 abort();
1068 });
1069 StartIntercept(&output_fd);
1070 FinishCrasher();
1071 AssertDeath(SIGABRT);
1072 FinishIntercept(&intercept_result);
1073
1074 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1075
1076 std::string result;
1077 ConsumeFd(std::move(output_fd), &result);
1078 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME\\1: 'crash_detail_value')");
1079}
1080
1081
1082TEST_F(CrasherTest, crash_detail_single_bytes) {
1083 int intercept_result;
1084 unique_fd output_fd;
1085 StartProcess([]() {
Florian Mayer920d95b2024-02-14 12:57:09 -08001086 android_crash_detail_register("CRASH_DETAIL_NAME", strlen("CRASH_DETAIL_NAME"), "\1",
Florian Mayer5fa66632024-02-07 16:42:23 -08001087 sizeof("\1"));
1088 abort();
1089 });
1090 StartIntercept(&output_fd);
1091 FinishCrasher();
1092 AssertDeath(SIGABRT);
1093 FinishIntercept(&intercept_result);
1094
1095 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1096
1097 std::string result;
1098 ConsumeFd(std::move(output_fd), &result);
1099 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: '\\1\\0')");
1100}
1101
1102TEST_F(CrasherTest, crash_detail_mixed) {
1103 int intercept_result;
1104 unique_fd output_fd;
1105 StartProcess([]() {
1106 const char data[] = "helloworld\1\255\3";
1107 android_register_crash_detail_strs("CRASH_DETAIL_NAME", data);
1108 abort();
1109 });
1110 StartIntercept(&output_fd);
1111 FinishCrasher();
1112 AssertDeath(SIGABRT);
1113 FinishIntercept(&intercept_result);
1114
1115 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1116
1117 std::string result;
1118 ConsumeFd(std::move(output_fd), &result);
1119 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'helloworld\\1\\255\\3')");
1120}
1121
1122TEST_F(CrasherTest, crash_detail_many) {
1123 int intercept_result;
1124 unique_fd output_fd;
1125 StartProcess([]() {
1126 for (int i = 0; i < 1000; ++i) {
1127 std::string name = "CRASH_DETAIL_NAME" + std::to_string(i);
1128 std::string value = "CRASH_DETAIL_VALUE" + std::to_string(i);
1129 auto* h = android_register_crash_detail_strs(name.data(), value.data());
Florian Mayer920d95b2024-02-14 12:57:09 -08001130 android_crash_detail_unregister(h);
Florian Mayer5fa66632024-02-07 16:42:23 -08001131 }
1132
1133 android_register_crash_detail_strs("FINAL_NAME", "FINAL_VALUE");
1134 android_register_crash_detail_strs("FINAL_NAME2", "FINAL_VALUE2");
1135 abort();
1136 });
1137 StartIntercept(&output_fd);
1138 FinishCrasher();
1139 AssertDeath(SIGABRT);
1140 FinishIntercept(&intercept_result);
1141
1142 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1143
1144 std::string result;
1145 ConsumeFd(std::move(output_fd), &result);
1146 ASSERT_NOT_MATCH(result, "CRASH_DETAIL_NAME");
1147 ASSERT_NOT_MATCH(result, "CRASH_DETAIL_VALUE");
1148 ASSERT_MATCH(result, R"(FINAL_NAME: 'FINAL_VALUE')");
1149 ASSERT_MATCH(result, R"(FINAL_NAME2: 'FINAL_VALUE2')");
1150}
1151
1152TEST_F(CrasherTest, crash_detail_single_changes) {
1153 int intercept_result;
1154 unique_fd output_fd;
1155 StartProcess([]() {
1156 android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value_changes);
1157 g_crash_detail_value_changes[0] = 'C';
1158 abort();
1159 });
1160 StartIntercept(&output_fd);
1161 FinishCrasher();
1162 AssertDeath(SIGABRT);
1163 FinishIntercept(&intercept_result);
1164
1165 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1166
1167 std::string result;
1168 ConsumeFd(std::move(output_fd), &result);
1169 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'Crash_detail_value')");
1170}
1171
1172TEST_F(CrasherTest, crash_detail_multiple) {
1173 int intercept_result;
1174 unique_fd output_fd;
1175 StartProcess([]() {
1176 android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value);
1177 android_register_crash_detail_strs("CRASH_DETAIL_NAME2", g_crash_detail_value2);
1178 abort();
1179 });
1180 StartIntercept(&output_fd);
1181 FinishCrasher();
1182 AssertDeath(SIGABRT);
1183 FinishIntercept(&intercept_result);
1184
1185 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1186
1187 std::string result;
1188 ConsumeFd(std::move(output_fd), &result);
1189 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME: 'crash_detail_value')");
1190 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME2: 'crash_detail_value2')");
1191}
1192
1193TEST_F(CrasherTest, crash_detail_remove) {
1194 int intercept_result;
1195 unique_fd output_fd;
1196 StartProcess([]() {
1197 auto* detail1 = android_register_crash_detail_strs("CRASH_DETAIL_NAME", g_crash_detail_value);
Florian Mayer920d95b2024-02-14 12:57:09 -08001198 android_crash_detail_unregister(detail1);
Florian Mayer5fa66632024-02-07 16:42:23 -08001199 android_register_crash_detail_strs("CRASH_DETAIL_NAME2", g_crash_detail_value2);
1200 abort();
1201 });
1202 StartIntercept(&output_fd);
1203 FinishCrasher();
1204 AssertDeath(SIGABRT);
1205 FinishIntercept(&intercept_result);
1206
1207 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1208
1209 std::string result;
1210 ConsumeFd(std::move(output_fd), &result);
1211 ASSERT_NOT_MATCH(result, R"(CRASH_DETAIL_NAME: 'crash_detail_value')");
1212 ASSERT_MATCH(result, R"(CRASH_DETAIL_NAME2: 'crash_detail_value2')");
1213}
1214
Christopher Ferrise8891452021-08-17 17:34:53 -07001215TEST_F(CrasherTest, abort_message_newline_trimmed) {
1216 int intercept_result;
1217 unique_fd output_fd;
1218 StartProcess([]() {
1219 android_set_abort_message("Message with a newline.\n");
1220 abort();
1221 });
1222 StartIntercept(&output_fd);
1223 FinishCrasher();
1224 AssertDeath(SIGABRT);
1225 FinishIntercept(&intercept_result);
1226
1227 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1228
1229 std::string result;
1230 ConsumeFd(std::move(output_fd), &result);
1231 ASSERT_MATCH(result, R"(Abort message: 'Message with a newline.')");
1232}
1233
1234TEST_F(CrasherTest, abort_message_multiple_newlines_trimmed) {
1235 int intercept_result;
1236 unique_fd output_fd;
1237 StartProcess([]() {
1238 android_set_abort_message("Message with multiple newlines.\n\n\n\n\n");
1239 abort();
1240 });
1241 StartIntercept(&output_fd);
1242 FinishCrasher();
1243 AssertDeath(SIGABRT);
1244 FinishIntercept(&intercept_result);
1245
1246 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1247
1248 std::string result;
1249 ConsumeFd(std::move(output_fd), &result);
1250 ASSERT_MATCH(result, R"(Abort message: 'Message with multiple newlines.')");
1251}
1252
Josh Gaoe06f2a42017-04-27 16:50:38 -07001253TEST_F(CrasherTest, abort_message_backtrace) {
1254 int intercept_result;
1255 unique_fd output_fd;
1256 StartProcess([]() {
1257 android_set_abort_message("not actually aborting");
Josh Gaoa48b41b2019-12-13 14:11:04 -08001258 raise(BIONIC_SIGNAL_DEBUGGER);
Josh Gaoe06f2a42017-04-27 16:50:38 -07001259 exit(0);
1260 });
1261 StartIntercept(&output_fd);
1262 FinishCrasher();
1263 AssertDeath(0);
1264 FinishIntercept(&intercept_result);
1265
1266 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1267
1268 std::string result;
1269 ConsumeFd(std::move(output_fd), &result);
1270 ASSERT_NOT_MATCH(result, R"(Abort message:)");
1271}
1272
Josh Gaocbe70cb2016-10-18 18:17:52 -07001273TEST_F(CrasherTest, intercept_timeout) {
1274 int intercept_result;
1275 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -08001276 StartProcess([]() {
1277 abort();
1278 });
Josh Gaocbe70cb2016-10-18 18:17:52 -07001279 StartIntercept(&output_fd);
1280
1281 // Don't let crasher finish until we timeout.
1282 FinishIntercept(&intercept_result);
1283
1284 ASSERT_NE(1, intercept_result) << "tombstoned reported success? (intercept_result = "
1285 << intercept_result << ")";
1286
1287 FinishCrasher();
1288 AssertDeath(SIGABRT);
1289}
1290
Elliott Hughese4781d52021-03-17 09:15:15 -07001291TEST_F(CrasherTest, wait_for_debugger) {
1292 if (!android::base::SetProperty(kWaitForDebuggerKey, "1")) {
1293 FAIL() << "failed to enable wait_for_debugger";
Josh Gaocbe70cb2016-10-18 18:17:52 -07001294 }
1295 sleep(1);
1296
Josh Gao502cfd22017-02-17 01:39:15 -08001297 StartProcess([]() {
1298 abort();
1299 });
Josh Gaocbe70cb2016-10-18 18:17:52 -07001300 FinishCrasher();
1301
1302 int status;
Christopher Ferris172b0a02019-09-18 17:48:30 -07001303 ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, WUNTRACED)));
Josh Gaocbe70cb2016-10-18 18:17:52 -07001304 ASSERT_TRUE(WIFSTOPPED(status));
1305 ASSERT_EQ(SIGSTOP, WSTOPSIG(status));
1306
1307 ASSERT_EQ(0, kill(crasher_pid, SIGCONT));
1308
1309 AssertDeath(SIGABRT);
1310}
1311
Josh Gaocbe70cb2016-10-18 18:17:52 -07001312TEST_F(CrasherTest, backtrace) {
1313 std::string result;
1314 int intercept_result;
1315 unique_fd output_fd;
Josh Gao502cfd22017-02-17 01:39:15 -08001316
1317 StartProcess([]() {
1318 abort();
1319 });
Narayan Kamatha73df602017-05-24 15:07:25 +01001320 StartIntercept(&output_fd, kDebuggerdNativeBacktrace);
Josh Gaocbe70cb2016-10-18 18:17:52 -07001321
1322 std::this_thread::sleep_for(500ms);
1323
1324 sigval val;
1325 val.sival_int = 1;
Josh Gaoa48b41b2019-12-13 14:11:04 -08001326 ASSERT_EQ(0, sigqueue(crasher_pid, BIONIC_SIGNAL_DEBUGGER, val)) << strerror(errno);
Josh Gaocbe70cb2016-10-18 18:17:52 -07001327 FinishIntercept(&intercept_result);
1328 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1329 ConsumeFd(std::move(output_fd), &result);
Jaesung Chung58778e12017-06-15 18:20:34 +09001330 ASSERT_BACKTRACE_FRAME(result, "read");
Josh Gaocbe70cb2016-10-18 18:17:52 -07001331
1332 int status;
1333 ASSERT_EQ(0, waitpid(crasher_pid, &status, WNOHANG | WUNTRACED));
1334
1335 StartIntercept(&output_fd);
1336 FinishCrasher();
1337 AssertDeath(SIGABRT);
1338 FinishIntercept(&intercept_result);
1339 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1340 ConsumeFd(std::move(output_fd), &result);
Andreas Gampe26cbafb2017-06-22 20:14:43 -07001341 ASSERT_BACKTRACE_FRAME(result, "abort");
Josh Gaocbe70cb2016-10-18 18:17:52 -07001342}
Josh Gaofca7ca32017-01-23 12:05:35 -08001343
1344TEST_F(CrasherTest, PR_SET_DUMPABLE_0_crash) {
Josh Gao502cfd22017-02-17 01:39:15 -08001345 int intercept_result;
1346 unique_fd output_fd;
Josh Gaofca7ca32017-01-23 12:05:35 -08001347 StartProcess([]() {
1348 prctl(PR_SET_DUMPABLE, 0);
Josh Gao502cfd22017-02-17 01:39:15 -08001349 abort();
Josh Gaofca7ca32017-01-23 12:05:35 -08001350 });
Josh Gao502cfd22017-02-17 01:39:15 -08001351
1352 StartIntercept(&output_fd);
1353 FinishCrasher();
1354 AssertDeath(SIGABRT);
1355 FinishIntercept(&intercept_result);
1356
1357 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1358
1359 std::string result;
1360 ConsumeFd(std::move(output_fd), &result);
Andreas Gampe26cbafb2017-06-22 20:14:43 -07001361 ASSERT_BACKTRACE_FRAME(result, "abort");
Josh Gaofca7ca32017-01-23 12:05:35 -08001362}
1363
Josh Gao502cfd22017-02-17 01:39:15 -08001364TEST_F(CrasherTest, capabilities) {
1365 ASSERT_EQ(0U, getuid()) << "capability test requires root";
1366
Josh Gaofca7ca32017-01-23 12:05:35 -08001367 StartProcess([]() {
Josh Gao502cfd22017-02-17 01:39:15 -08001368 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
1369 err(1, "failed to set PR_SET_KEEPCAPS");
1370 }
1371
1372 if (setresuid(1, 1, 1) != 0) {
1373 err(1, "setresuid failed");
1374 }
1375
1376 __user_cap_header_struct capheader;
1377 __user_cap_data_struct capdata[2];
1378 memset(&capheader, 0, sizeof(capheader));
1379 memset(&capdata, 0, sizeof(capdata));
1380
1381 capheader.version = _LINUX_CAPABILITY_VERSION_3;
1382 capheader.pid = 0;
1383
1384 // Turn on every third capability.
1385 static_assert(CAP_LAST_CAP > 33, "CAP_LAST_CAP <= 32");
1386 for (int i = 0; i < CAP_LAST_CAP; i += 3) {
1387 capdata[CAP_TO_INDEX(i)].permitted |= CAP_TO_MASK(i);
1388 capdata[CAP_TO_INDEX(i)].effective |= CAP_TO_MASK(i);
1389 }
1390
1391 // Make sure CAP_SYS_PTRACE is off.
1392 capdata[CAP_TO_INDEX(CAP_SYS_PTRACE)].permitted &= ~(CAP_TO_MASK(CAP_SYS_PTRACE));
1393 capdata[CAP_TO_INDEX(CAP_SYS_PTRACE)].effective &= ~(CAP_TO_MASK(CAP_SYS_PTRACE));
1394
1395 if (capset(&capheader, &capdata[0]) != 0) {
1396 err(1, "capset failed");
1397 }
1398
1399 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0) != 0) {
1400 err(1, "failed to drop ambient capabilities");
1401 }
1402
Josh Gaoa5199a92017-04-03 13:18:34 -07001403 pthread_setname_np(pthread_self(), "thread_name");
Josh Gao502cfd22017-02-17 01:39:15 -08001404 raise(SIGSYS);
Josh Gaofca7ca32017-01-23 12:05:35 -08001405 });
Josh Gao502cfd22017-02-17 01:39:15 -08001406
1407 unique_fd output_fd;
1408 StartIntercept(&output_fd);
1409 FinishCrasher();
1410 AssertDeath(SIGSYS);
1411
1412 std::string result;
1413 int intercept_result;
1414 FinishIntercept(&intercept_result);
1415 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1416 ConsumeFd(std::move(output_fd), &result);
Josh Gaoa5199a92017-04-03 13:18:34 -07001417 ASSERT_MATCH(result, R"(name: thread_name\s+>>> .+debuggerd_test(32|64) <<<)");
Jaesung Chung58778e12017-06-15 18:20:34 +09001418 ASSERT_BACKTRACE_FRAME(result, "tgkill");
Josh Gaofca7ca32017-01-23 12:05:35 -08001419}
Josh Gaoc3c8c022017-02-13 16:36:18 -08001420
Josh Gao2e7b8e22017-05-04 17:12:57 -07001421TEST_F(CrasherTest, fake_pid) {
1422 int intercept_result;
1423 unique_fd output_fd;
1424
1425 // Prime the getpid/gettid caches.
1426 UNUSED(getpid());
1427 UNUSED(gettid());
1428
1429 std::function<pid_t()> clone_fn = []() {
1430 return syscall(__NR_clone, SIGCHLD, nullptr, nullptr, nullptr, nullptr);
1431 };
1432 StartProcess(
1433 []() {
1434 ASSERT_NE(getpid(), syscall(__NR_getpid));
1435 ASSERT_NE(gettid(), syscall(__NR_gettid));
1436 raise(SIGSEGV);
1437 },
1438 clone_fn);
1439
1440 StartIntercept(&output_fd);
1441 FinishCrasher();
1442 AssertDeath(SIGSEGV);
1443 FinishIntercept(&intercept_result);
1444
1445 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1446
1447 std::string result;
1448 ConsumeFd(std::move(output_fd), &result);
Jaesung Chung58778e12017-06-15 18:20:34 +09001449 ASSERT_BACKTRACE_FRAME(result, "tgkill");
Josh Gao2e7b8e22017-05-04 17:12:57 -07001450}
1451
Josh Gaoe04ca272018-01-16 15:38:17 -08001452static const char* const kDebuggerdSeccompPolicy =
1453 "/system/etc/seccomp_policy/crash_dump." ABI_STRING ".policy";
1454
Mitch Phillips18ce5422023-01-19 14:23:49 -08001455static void setup_jail(minijail* jail) {
1456 if (!jail) {
1457 LOG(FATAL) << "failed to create minijail";
1458 }
1459
Josh Gao6f9eeec2018-09-12 13:55:47 -07001460 std::string policy;
1461 if (!android::base::ReadFileToString(kDebuggerdSeccompPolicy, &policy)) {
1462 PLOG(FATAL) << "failed to read policy file";
1463 }
1464
1465 // Allow a bunch of syscalls used by the tests.
1466 policy += "\nclone: 1";
1467 policy += "\nsigaltstack: 1";
1468 policy += "\nnanosleep: 1";
Christopher Ferrisab606682019-09-17 15:31:47 -07001469 policy += "\ngetrlimit: 1";
1470 policy += "\nugetrlimit: 1";
Josh Gao6f9eeec2018-09-12 13:55:47 -07001471
1472 FILE* tmp_file = tmpfile();
1473 if (!tmp_file) {
1474 PLOG(FATAL) << "tmpfile failed";
1475 }
1476
Christopher Ferris172b0a02019-09-18 17:48:30 -07001477 unique_fd tmp_fd(TEMP_FAILURE_RETRY(dup(fileno(tmp_file))));
Josh Gao6f9eeec2018-09-12 13:55:47 -07001478 if (!android::base::WriteStringToFd(policy, tmp_fd.get())) {
1479 PLOG(FATAL) << "failed to write policy to tmpfile";
1480 }
1481
1482 if (lseek(tmp_fd.get(), 0, SEEK_SET) != 0) {
1483 PLOG(FATAL) << "failed to seek tmp_fd";
Josh Gaoe04ca272018-01-16 15:38:17 -08001484 }
1485
Mitch Phillips18ce5422023-01-19 14:23:49 -08001486 minijail_no_new_privs(jail);
1487 minijail_log_seccomp_filter_failures(jail);
1488 minijail_use_seccomp_filter(jail);
1489 minijail_parse_seccomp_filters_from_fd(jail, tmp_fd.release());
1490}
Josh Gaoe04ca272018-01-16 15:38:17 -08001491
Mitch Phillips18ce5422023-01-19 14:23:49 -08001492static pid_t seccomp_fork_impl(void (*prejail)()) {
1493 ScopedMinijail jail{minijail_new()};
1494 setup_jail(jail.get());
Josh Gaoe04ca272018-01-16 15:38:17 -08001495
1496 pid_t result = fork();
1497 if (result == -1) {
1498 return result;
1499 } else if (result != 0) {
1500 return result;
1501 }
1502
1503 // Spawn and detach a thread that spins forever.
1504 std::atomic<bool> thread_ready(false);
1505 std::thread thread([&jail, &thread_ready]() {
1506 minijail_enter(jail.get());
1507 thread_ready = true;
1508 for (;;)
1509 ;
1510 });
1511 thread.detach();
1512
1513 while (!thread_ready) {
1514 continue;
1515 }
1516
Josh Gao70adac62018-02-22 11:38:33 -08001517 if (prejail) {
1518 prejail();
1519 }
1520
Josh Gaoe04ca272018-01-16 15:38:17 -08001521 minijail_enter(jail.get());
1522 return result;
1523}
1524
Josh Gao70adac62018-02-22 11:38:33 -08001525static pid_t seccomp_fork() {
1526 return seccomp_fork_impl(nullptr);
1527}
1528
Josh Gaoe04ca272018-01-16 15:38:17 -08001529TEST_F(CrasherTest, seccomp_crash) {
1530 int intercept_result;
1531 unique_fd output_fd;
1532
1533 StartProcess([]() { abort(); }, &seccomp_fork);
1534
1535 StartIntercept(&output_fd);
1536 FinishCrasher();
1537 AssertDeath(SIGABRT);
1538 FinishIntercept(&intercept_result);
1539 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1540
1541 std::string result;
1542 ConsumeFd(std::move(output_fd), &result);
1543 ASSERT_BACKTRACE_FRAME(result, "abort");
1544}
1545
Josh Gao70adac62018-02-22 11:38:33 -08001546static pid_t seccomp_fork_rlimit() {
1547 return seccomp_fork_impl([]() {
1548 struct rlimit rlim = {
1549 .rlim_cur = 512 * 1024 * 1024,
1550 .rlim_max = 512 * 1024 * 1024,
1551 };
1552
1553 if (setrlimit(RLIMIT_AS, &rlim) != 0) {
1554 raise(SIGINT);
1555 }
1556 });
1557}
1558
1559TEST_F(CrasherTest, seccomp_crash_oom) {
1560 int intercept_result;
1561 unique_fd output_fd;
1562
1563 StartProcess(
1564 []() {
1565 std::vector<void*> vec;
1566 for (int i = 0; i < 512; ++i) {
1567 char* buf = static_cast<char*>(malloc(1024 * 1024));
1568 if (!buf) {
1569 abort();
1570 }
1571 memset(buf, 0xff, 1024 * 1024);
1572 vec.push_back(buf);
1573 }
1574 },
1575 &seccomp_fork_rlimit);
1576
1577 StartIntercept(&output_fd);
1578 FinishCrasher();
1579 AssertDeath(SIGABRT);
1580 FinishIntercept(&intercept_result);
1581 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1582
1583 // We can't actually generate a backtrace, just make sure that the process terminates.
1584}
1585
Elliott Hughesb795d6f2022-09-14 20:15:19 +00001586__attribute__((__noinline__)) extern "C" bool raise_debugger_signal(DebuggerdDumpType dump_type) {
Josh Gaoe04ca272018-01-16 15:38:17 -08001587 siginfo_t siginfo;
1588 siginfo.si_code = SI_QUEUE;
1589 siginfo.si_pid = getpid();
1590 siginfo.si_uid = getuid();
1591
1592 if (dump_type != kDebuggerdNativeBacktrace && dump_type != kDebuggerdTombstone) {
1593 PLOG(FATAL) << "invalid dump type";
1594 }
1595
1596 siginfo.si_value.sival_int = dump_type == kDebuggerdNativeBacktrace;
1597
Josh Gaoa48b41b2019-12-13 14:11:04 -08001598 if (syscall(__NR_rt_tgsigqueueinfo, getpid(), gettid(), BIONIC_SIGNAL_DEBUGGER, &siginfo) != 0) {
Josh Gaoe04ca272018-01-16 15:38:17 -08001599 PLOG(ERROR) << "libdebuggerd_client: failed to send signal to self";
1600 return false;
1601 }
1602
1603 return true;
1604}
1605
Christopher Ferrisb999b822022-02-09 17:57:21 -08001606extern "C" void foo() {
1607 LOG(INFO) << "foo";
1608 std::this_thread::sleep_for(1s);
1609}
1610
1611extern "C" void bar() {
1612 LOG(INFO) << "bar";
1613 std::this_thread::sleep_for(1s);
1614}
1615
Josh Gaoe04ca272018-01-16 15:38:17 -08001616TEST_F(CrasherTest, seccomp_tombstone) {
1617 int intercept_result;
1618 unique_fd output_fd;
1619
1620 static const auto dump_type = kDebuggerdTombstone;
1621 StartProcess(
1622 []() {
Christopher Ferrisb999b822022-02-09 17:57:21 -08001623 std::thread a(foo);
1624 std::thread b(bar);
1625
1626 std::this_thread::sleep_for(100ms);
1627
Josh Gaoe04ca272018-01-16 15:38:17 -08001628 raise_debugger_signal(dump_type);
1629 _exit(0);
1630 },
1631 &seccomp_fork);
1632
1633 StartIntercept(&output_fd, dump_type);
1634 FinishCrasher();
1635 AssertDeath(0);
1636 FinishIntercept(&intercept_result);
1637 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1638
1639 std::string result;
1640 ConsumeFd(std::move(output_fd), &result);
1641 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
Christopher Ferrisb999b822022-02-09 17:57:21 -08001642 ASSERT_BACKTRACE_FRAME(result, "foo");
1643 ASSERT_BACKTRACE_FRAME(result, "bar");
Josh Gao6f9eeec2018-09-12 13:55:47 -07001644}
1645
Christopher Ferris303c6be2022-05-24 17:08:33 -07001646TEST_F(CrasherTest, seccomp_tombstone_thread_abort) {
1647 int intercept_result;
1648 unique_fd output_fd;
1649
1650 static const auto dump_type = kDebuggerdTombstone;
1651 StartProcess(
1652 []() {
1653 std::thread abort_thread([] { abort(); });
1654 abort_thread.join();
1655 },
1656 &seccomp_fork);
1657
1658 StartIntercept(&output_fd, dump_type);
1659 FinishCrasher();
1660 AssertDeath(SIGABRT);
1661 FinishIntercept(&intercept_result);
1662 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1663
1664 std::string result;
1665 ConsumeFd(std::move(output_fd), &result);
Xiaohui Niu7bfbe412024-04-26 11:08:15 +08001666 ASSERT_MATCH(
1667 result,
1668 R"(signal 6 \(SIGABRT\))");
Christopher Ferris303c6be2022-05-24 17:08:33 -07001669 ASSERT_BACKTRACE_FRAME(result, "abort");
1670}
1671
Christopher Ferris7c2e7e32022-05-27 12:57:58 -07001672TEST_F(CrasherTest, seccomp_tombstone_multiple_threads_abort) {
1673 int intercept_result;
1674 unique_fd output_fd;
1675
1676 static const auto dump_type = kDebuggerdTombstone;
1677 StartProcess(
1678 []() {
1679 std::thread a(foo);
1680 std::thread b(bar);
1681
1682 std::this_thread::sleep_for(100ms);
1683
1684 std::thread abort_thread([] { abort(); });
1685 abort_thread.join();
1686 },
1687 &seccomp_fork);
1688
1689 StartIntercept(&output_fd, dump_type);
1690 FinishCrasher();
1691 AssertDeath(SIGABRT);
1692 FinishIntercept(&intercept_result);
1693 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1694
1695 std::string result;
1696 ConsumeFd(std::move(output_fd), &result);
1697 ASSERT_BACKTRACE_FRAME(result, "abort");
1698 ASSERT_BACKTRACE_FRAME(result, "foo");
1699 ASSERT_BACKTRACE_FRAME(result, "bar");
1700 ASSERT_BACKTRACE_FRAME(result, "main");
1701}
1702
Josh Gaoe04ca272018-01-16 15:38:17 -08001703TEST_F(CrasherTest, seccomp_backtrace) {
1704 int intercept_result;
1705 unique_fd output_fd;
1706
1707 static const auto dump_type = kDebuggerdNativeBacktrace;
1708 StartProcess(
1709 []() {
Josh Gao6f9eeec2018-09-12 13:55:47 -07001710 std::thread a(foo);
1711 std::thread b(bar);
1712
1713 std::this_thread::sleep_for(100ms);
1714
Josh Gaoe04ca272018-01-16 15:38:17 -08001715 raise_debugger_signal(dump_type);
1716 _exit(0);
1717 },
1718 &seccomp_fork);
1719
1720 StartIntercept(&output_fd, dump_type);
1721 FinishCrasher();
1722 AssertDeath(0);
1723 FinishIntercept(&intercept_result);
1724 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1725
1726 std::string result;
1727 ConsumeFd(std::move(output_fd), &result);
1728 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
Josh Gao6f9eeec2018-09-12 13:55:47 -07001729 ASSERT_BACKTRACE_FRAME(result, "foo");
1730 ASSERT_BACKTRACE_FRAME(result, "bar");
Josh Gaoe04ca272018-01-16 15:38:17 -08001731}
1732
Christopher Ferris7c2e7e32022-05-27 12:57:58 -07001733TEST_F(CrasherTest, seccomp_backtrace_from_thread) {
1734 int intercept_result;
1735 unique_fd output_fd;
1736
1737 static const auto dump_type = kDebuggerdNativeBacktrace;
1738 StartProcess(
1739 []() {
1740 std::thread a(foo);
1741 std::thread b(bar);
1742
1743 std::this_thread::sleep_for(100ms);
1744
1745 std::thread raise_thread([] {
1746 raise_debugger_signal(dump_type);
1747 _exit(0);
1748 });
1749 raise_thread.join();
1750 },
1751 &seccomp_fork);
1752
1753 StartIntercept(&output_fd, dump_type);
1754 FinishCrasher();
1755 AssertDeath(0);
1756 FinishIntercept(&intercept_result);
1757 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1758
1759 std::string result;
1760 ConsumeFd(std::move(output_fd), &result);
1761 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
1762 ASSERT_BACKTRACE_FRAME(result, "foo");
1763 ASSERT_BACKTRACE_FRAME(result, "bar");
1764 ASSERT_BACKTRACE_FRAME(result, "main");
1765}
1766
Josh Gaoe04ca272018-01-16 15:38:17 -08001767TEST_F(CrasherTest, seccomp_crash_logcat) {
1768 StartProcess([]() { abort(); }, &seccomp_fork);
1769 FinishCrasher();
1770
1771 // Make sure we don't get SIGSYS when trying to dump a crash to logcat.
1772 AssertDeath(SIGABRT);
1773}
1774
Josh Gaofd13bf02017-08-18 15:37:26 -07001775TEST_F(CrasherTest, competing_tracer) {
1776 int intercept_result;
1777 unique_fd output_fd;
1778 StartProcess([]() {
Josh Gao2b2ae0c2017-08-21 14:31:17 -07001779 raise(SIGABRT);
Josh Gaofd13bf02017-08-18 15:37:26 -07001780 });
1781
1782 StartIntercept(&output_fd);
Josh Gaofd13bf02017-08-18 15:37:26 -07001783
1784 ASSERT_EQ(0, ptrace(PTRACE_SEIZE, crasher_pid, 0, 0));
Josh Gao2b2ae0c2017-08-21 14:31:17 -07001785 FinishCrasher();
Josh Gaofd13bf02017-08-18 15:37:26 -07001786
1787 int status;
Christopher Ferris172b0a02019-09-18 17:48:30 -07001788 ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
Josh Gaofd13bf02017-08-18 15:37:26 -07001789 ASSERT_TRUE(WIFSTOPPED(status));
1790 ASSERT_EQ(SIGABRT, WSTOPSIG(status));
1791
1792 ASSERT_EQ(0, ptrace(PTRACE_CONT, crasher_pid, 0, SIGABRT));
1793 FinishIntercept(&intercept_result);
1794 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1795
1796 std::string result;
1797 ConsumeFd(std::move(output_fd), &result);
1798 std::string regex = R"(failed to attach to thread \d+, already traced by )";
1799 regex += std::to_string(gettid());
1800 regex += R"( \(.+debuggerd_test)";
1801 ASSERT_MATCH(result, regex.c_str());
1802
Christopher Ferris172b0a02019-09-18 17:48:30 -07001803 ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
Josh Gao2b2ae0c2017-08-21 14:31:17 -07001804 ASSERT_TRUE(WIFSTOPPED(status));
1805 ASSERT_EQ(SIGABRT, WSTOPSIG(status));
1806
Josh Gaofd13bf02017-08-18 15:37:26 -07001807 ASSERT_EQ(0, ptrace(PTRACE_DETACH, crasher_pid, 0, SIGABRT));
1808 AssertDeath(SIGABRT);
1809}
1810
Mitch Phillips18ce5422023-01-19 14:23:49 -08001811struct GwpAsanTestParameters {
1812 size_t alloc_size;
1813 bool free_before_access;
1814 int access_offset;
1815 std::string cause_needle; // Needle to be found in the "Cause: [GWP-ASan]" line.
1816};
1817
1818struct GwpAsanCrasherTest
1819 : CrasherTest,
1820 testing::WithParamInterface<
1821 std::tuple<GwpAsanTestParameters, /* recoverable */ bool, /* seccomp */ bool>> {};
1822
1823GwpAsanTestParameters gwp_asan_tests[] = {
1824 {/* alloc_size */ 7, /* free_before_access */ true, /* access_offset */ 0,
1825 "Use After Free, 0 bytes into a 7-byte allocation"},
1826 {/* alloc_size */ 15, /* free_before_access */ true, /* access_offset */ 1,
1827 "Use After Free, 1 byte into a 15-byte allocation"},
Christopher Ferris2f77c2a2024-05-07 12:25:31 -07001828 {/* alloc_size */ static_cast<size_t>(getpagesize()), /* free_before_access */ false,
1829 /* access_offset */ getpagesize() + 2,
1830 android::base::StringPrintf("Buffer Overflow, 2 bytes right of a %d-byte allocation",
1831 getpagesize())},
1832 {/* alloc_size */ static_cast<size_t>(getpagesize()), /* free_before_access */ false,
1833 /* access_offset */ -1,
1834 android::base::StringPrintf("Buffer Underflow, 1 byte left of a %d-byte allocation",
1835 getpagesize())},
Mitch Phillips18ce5422023-01-19 14:23:49 -08001836};
1837
1838INSTANTIATE_TEST_SUITE_P(
1839 GwpAsanTests, GwpAsanCrasherTest,
1840 testing::Combine(testing::ValuesIn(gwp_asan_tests),
1841 /* recoverable */ testing::Bool(),
1842 /* seccomp */ testing::Bool()),
1843 [](const testing::TestParamInfo<
1844 std::tuple<GwpAsanTestParameters, /* recoverable */ bool, /* seccomp */ bool>>& info) {
1845 const GwpAsanTestParameters& params = std::get<0>(info.param);
1846 std::string name = params.free_before_access ? "UseAfterFree" : "Overflow";
1847 name += testing::PrintToString(params.alloc_size);
1848 name += "Alloc";
1849 if (params.access_offset < 0) {
1850 name += "Left";
1851 name += testing::PrintToString(params.access_offset * -1);
1852 } else {
1853 name += "Right";
1854 name += testing::PrintToString(params.access_offset);
1855 }
1856 name += "Bytes";
1857 if (std::get<1>(info.param)) name += "Recoverable";
1858 if (std::get<2>(info.param)) name += "Seccomp";
1859 return name;
1860 });
1861
1862TEST_P(GwpAsanCrasherTest, run_gwp_asan_test) {
1863 if (mte_supported()) {
1864 // Skip this test on MTE hardware, as MTE will reliably catch these errors
1865 // instead of GWP-ASan.
1866 GTEST_SKIP() << "Skipped on MTE.";
1867 }
1868 // Skip this test on HWASan, which will reliably catch test errors as well.
1869 SKIP_WITH_HWASAN;
1870
1871 GwpAsanTestParameters params = std::get<0>(GetParam());
1872 bool recoverable = std::get<1>(GetParam());
1873 LogcatCollector logcat_collector;
1874
1875 int intercept_result;
1876 unique_fd output_fd;
1877 StartProcess([&recoverable]() {
1878 const char* env[] = {"GWP_ASAN_SAMPLE_RATE=1", "GWP_ASAN_PROCESS_SAMPLING=1",
1879 "GWP_ASAN_MAX_ALLOCS=40000", nullptr, nullptr};
Mitch Phillipsa2f53352024-04-09 15:59:12 +02001880 if (!recoverable) {
1881 env[3] = "GWP_ASAN_RECOVERABLE=false";
Mitch Phillips18ce5422023-01-19 14:23:49 -08001882 }
1883 std::string test_name = ::testing::UnitTest::GetInstance()->current_test_info()->name();
1884 test_name = std::regex_replace(test_name, std::regex("run_gwp_asan_test"),
1885 "DISABLED_run_gwp_asan_test");
1886 std::string test_filter = "--gtest_filter=*";
1887 test_filter += test_name;
1888 std::string this_binary = android::base::GetExecutablePath();
1889 const char* args[] = {this_binary.c_str(), "--gtest_also_run_disabled_tests",
1890 test_filter.c_str(), nullptr};
1891 // We check the crash report from a debuggerd handler and from logcat. The
1892 // echo from stdout/stderr of the subprocess trips up atest, because it
1893 // doesn't like that two tests started in a row without the first one
1894 // finishing (even though the second one is in a subprocess).
1895 close(STDOUT_FILENO);
1896 close(STDERR_FILENO);
1897 execve(this_binary.c_str(), const_cast<char**>(args), const_cast<char**>(env));
1898 });
1899
1900 StartIntercept(&output_fd);
1901 FinishCrasher();
1902 if (recoverable) {
1903 AssertDeath(0);
1904 } else {
1905 AssertDeath(SIGSEGV);
1906 }
1907 FinishIntercept(&intercept_result);
1908
1909 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1910
1911 std::vector<std::string> log_sources(2);
1912 ConsumeFd(std::move(output_fd), &log_sources[0]);
1913 logcat_collector.Collect(&log_sources[1]);
1914
1915 // seccomp forces the fallback handler, which doesn't print GWP-ASan debugging
1916 // information. Make sure the recovery still works, but the report won't be
1917 // hugely useful, it looks like a regular SEGV.
1918 bool seccomp = std::get<2>(GetParam());
1919 if (!seccomp) {
1920 for (const auto& result : log_sources) {
1921 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\))");
1922 ASSERT_MATCH(result, R"(Cause: \[GWP-ASan\]: )" + params.cause_needle);
1923 if (params.free_before_access) {
1924 ASSERT_MATCH(result, R"(deallocated by thread .*\n.*#00 pc)");
1925 }
1926 ASSERT_MATCH(result, R"((^|\s)allocated by thread .*\n.*#00 pc)");
1927 }
1928 }
1929}
1930
1931TEST_P(GwpAsanCrasherTest, DISABLED_run_gwp_asan_test) {
1932 GwpAsanTestParameters params = std::get<0>(GetParam());
1933 bool seccomp = std::get<2>(GetParam());
1934 if (seccomp) {
1935 ScopedMinijail jail{minijail_new()};
1936 setup_jail(jail.get());
1937 minijail_enter(jail.get());
1938 }
1939
1940 // Use 'volatile' to prevent a very clever compiler eliminating the store.
1941 char* volatile p = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1942 if (params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
1943 p[params.access_offset] = 42;
1944 if (!params.free_before_access) free(static_cast<void*>(const_cast<char*>(p)));
Mitch Phillips70aa2192023-02-22 11:31:36 -08001945
1946 bool recoverable = std::get<1>(GetParam());
1947 ASSERT_TRUE(recoverable); // Non-recoverable should have crashed.
1948
1949 // As we're in recoverable mode, trigger another 2x use-after-frees (ensuring
1950 // we end with at least one in a different slot), make sure the process still
1951 // doesn't crash.
1952 p = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1953 char* volatile p2 = reinterpret_cast<char* volatile>(malloc(params.alloc_size));
1954 free(static_cast<void*>(const_cast<char*>(p)));
1955 free(static_cast<void*>(const_cast<char*>(p2)));
1956 *p = 42;
1957 *p2 = 42;
1958
1959 // Under clang coverage (which is a default TEST_MAPPING presubmit target), the
1960 // recoverable+seccomp tests fail because the minijail prevents some atexit syscalls that clang
1961 // coverage does. Thus, skip the atexit handlers.
1962 _exit(0);
Mitch Phillips18ce5422023-01-19 14:23:49 -08001963}
1964
Josh Gaobf06a402018-08-27 16:34:01 -07001965TEST_F(CrasherTest, fdsan_warning_abort_message) {
1966 int intercept_result;
1967 unique_fd output_fd;
1968
1969 StartProcess([]() {
1970 android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
Christopher Ferris172b0a02019-09-18 17:48:30 -07001971 unique_fd fd(TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY | O_CLOEXEC)));
Josh Gaobf06a402018-08-27 16:34:01 -07001972 if (fd == -1) {
1973 abort();
1974 }
1975 close(fd.get());
1976 _exit(0);
1977 });
1978
1979 StartIntercept(&output_fd);
1980 FinishCrasher();
1981 AssertDeath(0);
1982 FinishIntercept(&intercept_result);
1983 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
1984
1985 std::string result;
1986 ConsumeFd(std::move(output_fd), &result);
1987 ASSERT_MATCH(result, "Abort message: 'attempted to close");
1988}
1989
Josh Gaoc3c8c022017-02-13 16:36:18 -08001990TEST(crash_dump, zombie) {
1991 pid_t forkpid = fork();
1992
Josh Gaoc3c8c022017-02-13 16:36:18 -08001993 pid_t rc;
1994 int status;
1995
1996 if (forkpid == 0) {
1997 errno = 0;
1998 rc = waitpid(-1, &status, WNOHANG | __WALL | __WNOTHREAD);
1999 if (rc != -1 || errno != ECHILD) {
2000 errx(2, "first waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
2001 }
2002
Josh Gaoa48b41b2019-12-13 14:11:04 -08002003 raise(BIONIC_SIGNAL_DEBUGGER);
Josh Gaoc3c8c022017-02-13 16:36:18 -08002004
2005 errno = 0;
Christopher Ferris172b0a02019-09-18 17:48:30 -07002006 rc = TEMP_FAILURE_RETRY(waitpid(-1, &status, __WALL | __WNOTHREAD));
Josh Gaoc3c8c022017-02-13 16:36:18 -08002007 if (rc != -1 || errno != ECHILD) {
2008 errx(2, "second waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
2009 }
2010 _exit(0);
2011 } else {
Christopher Ferris172b0a02019-09-18 17:48:30 -07002012 rc = TEMP_FAILURE_RETRY(waitpid(forkpid, &status, 0));
Josh Gaoc3c8c022017-02-13 16:36:18 -08002013 ASSERT_EQ(forkpid, rc);
2014 ASSERT_TRUE(WIFEXITED(status));
2015 ASSERT_EQ(0, WEXITSTATUS(status));
2016 }
2017}
Josh Gao352a8452017-03-30 16:46:21 -07002018
2019TEST(tombstoned, no_notify) {
2020 // Do this a few times.
2021 for (int i = 0; i < 3; ++i) {
2022 pid_t pid = 123'456'789 + i;
2023
2024 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002025 InterceptResponse response = {};
2026 tombstoned_intercept(pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2027 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2028 << "Error message: " << response.error_message;
Josh Gao352a8452017-03-30 16:46:21 -07002029
2030 {
2031 unique_fd tombstoned_socket, input_fd;
Narayan Kamatha73df602017-05-24 15:07:25 +01002032 ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
Josh Gao352a8452017-03-30 16:46:21 -07002033 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid)));
2034 }
2035
2036 pid_t read_pid;
2037 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid)));
2038 ASSERT_EQ(read_pid, pid);
2039 }
2040}
2041
2042TEST(tombstoned, stress) {
2043 // Spawn threads to simultaneously do a bunch of failing dumps and a bunch of successful dumps.
2044 static constexpr int kDumpCount = 100;
2045
2046 std::atomic<bool> start(false);
2047 std::vector<std::thread> threads;
2048 threads.emplace_back([&start]() {
2049 while (!start) {
2050 continue;
2051 }
2052
2053 // Use a way out of range pid, to avoid stomping on an actual process.
2054 pid_t pid_base = 1'000'000;
2055
2056 for (int dump = 0; dump < kDumpCount; ++dump) {
2057 pid_t pid = pid_base + dump;
2058
2059 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002060 InterceptResponse response = {};
2061 tombstoned_intercept(pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2062 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2063 << "Error messeage: " << response.error_message;
Josh Gao352a8452017-03-30 16:46:21 -07002064
2065 // Pretend to crash, and then immediately close the socket.
2066 unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName,
2067 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
2068 if (sockfd == -1) {
2069 FAIL() << "failed to connect to tombstoned: " << strerror(errno);
2070 }
2071 TombstonedCrashPacket packet = {};
2072 packet.packet_type = CrashPacketType::kDumpRequest;
2073 packet.packet.dump_request.pid = pid;
2074 if (TEMP_FAILURE_RETRY(write(sockfd, &packet, sizeof(packet))) != sizeof(packet)) {
2075 FAIL() << "failed to write to tombstoned: " << strerror(errno);
2076 }
2077
2078 continue;
2079 }
2080 });
2081
2082 threads.emplace_back([&start]() {
2083 while (!start) {
2084 continue;
2085 }
2086
2087 // Use a way out of range pid, to avoid stomping on an actual process.
2088 pid_t pid_base = 2'000'000;
2089
2090 for (int dump = 0; dump < kDumpCount; ++dump) {
2091 pid_t pid = pid_base + dump;
2092
2093 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002094 InterceptResponse response = {};
2095 tombstoned_intercept(pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2096 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2097 << "Error message: " << response.error_message;
Josh Gao352a8452017-03-30 16:46:21 -07002098
2099 {
2100 unique_fd tombstoned_socket, input_fd;
Narayan Kamatha73df602017-05-24 15:07:25 +01002101 ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
Josh Gao352a8452017-03-30 16:46:21 -07002102 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid)));
2103 tombstoned_notify_completion(tombstoned_socket.get());
2104 }
2105
2106 // TODO: Fix the race that requires this sleep.
2107 std::this_thread::sleep_for(50ms);
2108
2109 pid_t read_pid;
2110 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid)));
2111 ASSERT_EQ(read_pid, pid);
2112 }
2113 });
2114
2115 start = true;
2116
2117 for (std::thread& thread : threads) {
2118 thread.join();
2119 }
2120}
Narayan Kamathca5e9082017-06-02 15:42:06 +01002121
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002122TEST(tombstoned, intercept_java_trace_smoke) {
Narayan Kamathca5e9082017-06-02 15:42:06 +01002123 // Using a "real" PID is a little dangerous here - if the test fails
2124 // or crashes, we might end up getting a bogus / unreliable stack
2125 // trace.
2126 const pid_t self = getpid();
2127
2128 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002129 InterceptResponse response = {};
2130 tombstoned_intercept(self, &intercept_fd, &output_fd, &response, kDebuggerdJavaBacktrace);
2131 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2132 << "Error message: " << response.error_message;
Narayan Kamathca5e9082017-06-02 15:42:06 +01002133
Josh Gao76e1e302021-01-26 15:53:11 -08002134 // First connect to tombstoned requesting a native tombstone. This
Narayan Kamathca5e9082017-06-02 15:42:06 +01002135 // should result in a "regular" FD and not the installed intercept.
2136 const char native[] = "native";
2137 unique_fd tombstoned_socket, input_fd;
Josh Gao76e1e302021-01-26 15:53:11 -08002138 ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdTombstone));
Narayan Kamathca5e9082017-06-02 15:42:06 +01002139 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), native, sizeof(native)));
2140 tombstoned_notify_completion(tombstoned_socket.get());
2141
2142 // Then, connect to tombstoned asking for a java backtrace. This *should*
2143 // trigger the intercept.
2144 const char java[] = "java";
2145 ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdJavaBacktrace));
2146 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), java, sizeof(java)));
2147 tombstoned_notify_completion(tombstoned_socket.get());
2148
2149 char outbuf[sizeof(java)];
2150 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
2151 ASSERT_STREQ("java", outbuf);
2152}
2153
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002154TEST(tombstoned, intercept_multiple_dump_types) {
Narayan Kamathca5e9082017-06-02 15:42:06 +01002155 const pid_t fake_pid = 1'234'567;
2156 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002157 InterceptResponse response = {};
2158 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdJavaBacktrace);
2159 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2160 << "Error message: " << response.error_message;
Narayan Kamathca5e9082017-06-02 15:42:06 +01002161
2162 unique_fd intercept_fd_2, output_fd_2;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002163 tombstoned_intercept(fake_pid, &intercept_fd_2, &output_fd_2, &response,
2164 kDebuggerdNativeBacktrace);
2165 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2166 << "Error message: " << response.error_message;
2167}
2168
2169TEST(tombstoned, intercept_bad_pid) {
2170 const pid_t fake_pid = -1;
2171 unique_fd intercept_fd, output_fd;
2172 InterceptResponse response = {};
2173 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdNativeBacktrace);
2174 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2175 << "Error message: " << response.error_message;
2176 ASSERT_MATCH(response.error_message, "bad pid");
2177}
2178
2179TEST(tombstoned, intercept_bad_dump_types) {
2180 const pid_t fake_pid = 1'234'567;
2181 unique_fd intercept_fd, output_fd;
2182 InterceptResponse response = {};
2183 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response,
2184 static_cast<DebuggerdDumpType>(20));
2185 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2186 << "Error message: " << response.error_message;
2187 ASSERT_MATCH(response.error_message, "bad dump type \\[unknown\\]");
2188
2189 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdAnyIntercept);
2190 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2191 << "Error message: " << response.error_message;
2192 ASSERT_MATCH(response.error_message, "bad dump type kDebuggerdAnyIntercept");
2193
2194 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstoneProto);
2195 ASSERT_EQ(InterceptStatus::kFailed, response.status)
2196 << "Error message: " << response.error_message;
2197 ASSERT_MATCH(response.error_message, "bad dump type kDebuggerdTombstoneProto");
2198}
2199
2200TEST(tombstoned, intercept_already_registered) {
2201 const pid_t fake_pid = 1'234'567;
2202 unique_fd intercept_fd1, output_fd1;
2203 InterceptResponse response = {};
2204 tombstoned_intercept(fake_pid, &intercept_fd1, &output_fd1, &response, kDebuggerdTombstone);
2205 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2206 << "Error message: " << response.error_message;
2207
2208 unique_fd intercept_fd2, output_fd2;
2209 tombstoned_intercept(fake_pid, &intercept_fd2, &output_fd2, &response, kDebuggerdTombstone);
2210 ASSERT_EQ(InterceptStatus::kFailedAlreadyRegistered, response.status)
2211 << "Error message: " << response.error_message;
2212 ASSERT_MATCH(response.error_message, "already registered, type kDebuggerdTombstone");
2213}
2214
2215TEST(tombstoned, intercept_tombstone_proto_matched_to_tombstone) {
2216 const pid_t fake_pid = 1'234'567;
2217
2218 unique_fd intercept_fd, output_fd;
2219 InterceptResponse response = {};
2220 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2221 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2222 << "Error message: " << response.error_message;
2223
2224 const char data[] = "tombstone_proto";
2225 unique_fd tombstoned_socket, input_fd;
2226 ASSERT_TRUE(
2227 tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdTombstoneProto));
2228 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), data, sizeof(data)));
2229 tombstoned_notify_completion(tombstoned_socket.get());
2230
2231 char outbuf[sizeof(data)];
2232 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
2233 ASSERT_STREQ("tombstone_proto", outbuf);
Narayan Kamathca5e9082017-06-02 15:42:06 +01002234}
2235
2236TEST(tombstoned, intercept_any) {
2237 const pid_t fake_pid = 1'234'567;
2238
2239 unique_fd intercept_fd, output_fd;
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002240 InterceptResponse response = {};
2241 tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &response, kDebuggerdNativeBacktrace);
2242 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2243 << "Error message: " << response.error_message;
Narayan Kamathca5e9082017-06-02 15:42:06 +01002244
2245 const char any[] = "any";
2246 unique_fd tombstoned_socket, input_fd;
2247 ASSERT_TRUE(tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdAnyIntercept));
2248 ASSERT_TRUE(android::base::WriteFully(input_fd.get(), any, sizeof(any)));
2249 tombstoned_notify_completion(tombstoned_socket.get());
2250
2251 char outbuf[sizeof(any)];
2252 ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
2253 ASSERT_STREQ("any", outbuf);
2254}
Josh Gao2b22ae12018-09-12 14:51:03 -07002255
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002256TEST(tombstoned, intercept_any_failed_with_multiple_intercepts) {
2257 const pid_t fake_pid = 1'234'567;
2258
2259 InterceptResponse response = {};
2260 unique_fd intercept_fd1, output_fd1;
2261 tombstoned_intercept(fake_pid, &intercept_fd1, &output_fd1, &response, kDebuggerdNativeBacktrace);
2262 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2263 << "Error message: " << response.error_message;
2264
2265 unique_fd intercept_fd2, output_fd2;
2266 tombstoned_intercept(fake_pid, &intercept_fd2, &output_fd2, &response, kDebuggerdJavaBacktrace);
2267 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2268 << "Error message: " << response.error_message;
2269
2270 unique_fd tombstoned_socket, input_fd;
2271 ASSERT_FALSE(tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdAnyIntercept));
2272}
2273
2274TEST(tombstoned, intercept_multiple_verify_intercept) {
2275 // Need to use our pid for java since that will verify the pid.
2276 const pid_t fake_pid = getpid();
2277
2278 InterceptResponse response = {};
2279 unique_fd intercept_fd1, output_fd1;
2280 tombstoned_intercept(fake_pid, &intercept_fd1, &output_fd1, &response, kDebuggerdNativeBacktrace);
2281 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2282 << "Error message: " << response.error_message;
2283
2284 unique_fd intercept_fd2, output_fd2;
2285 tombstoned_intercept(fake_pid, &intercept_fd2, &output_fd2, &response, kDebuggerdJavaBacktrace);
2286 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2287 << "Error message: " << response.error_message;
2288
2289 unique_fd intercept_fd3, output_fd3;
2290 tombstoned_intercept(fake_pid, &intercept_fd3, &output_fd3, &response, kDebuggerdTombstone);
2291 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2292 << "Error message: " << response.error_message;
2293
2294 const char native_data[] = "native";
2295 unique_fd tombstoned_socket1, input_fd1;
2296 ASSERT_TRUE(
2297 tombstoned_connect(fake_pid, &tombstoned_socket1, &input_fd1, kDebuggerdNativeBacktrace));
2298 ASSERT_TRUE(android::base::WriteFully(input_fd1.get(), native_data, sizeof(native_data)));
2299 tombstoned_notify_completion(tombstoned_socket1.get());
2300
2301 char native_outbuf[sizeof(native_data)];
2302 ASSERT_TRUE(android::base::ReadFully(output_fd1.get(), native_outbuf, sizeof(native_outbuf)));
2303 ASSERT_STREQ("native", native_outbuf);
2304
2305 const char java_data[] = "java";
2306 unique_fd tombstoned_socket2, input_fd2;
2307 ASSERT_TRUE(
2308 tombstoned_connect(fake_pid, &tombstoned_socket2, &input_fd2, kDebuggerdJavaBacktrace));
2309 ASSERT_TRUE(android::base::WriteFully(input_fd2.get(), java_data, sizeof(java_data)));
2310 tombstoned_notify_completion(tombstoned_socket2.get());
2311
2312 char java_outbuf[sizeof(java_data)];
2313 ASSERT_TRUE(android::base::ReadFully(output_fd2.get(), java_outbuf, sizeof(java_outbuf)));
2314 ASSERT_STREQ("java", java_outbuf);
2315
2316 const char tomb_data[] = "tombstone";
2317 unique_fd tombstoned_socket3, input_fd3;
2318 ASSERT_TRUE(tombstoned_connect(fake_pid, &tombstoned_socket3, &input_fd3, kDebuggerdTombstone));
2319 ASSERT_TRUE(android::base::WriteFully(input_fd3.get(), tomb_data, sizeof(tomb_data)));
2320 tombstoned_notify_completion(tombstoned_socket3.get());
2321
2322 char tomb_outbuf[sizeof(tomb_data)];
2323 ASSERT_TRUE(android::base::ReadFully(output_fd3.get(), tomb_outbuf, sizeof(tomb_outbuf)));
2324 ASSERT_STREQ("tombstone", tomb_outbuf);
2325}
2326
Josh Gao2b22ae12018-09-12 14:51:03 -07002327TEST(tombstoned, interceptless_backtrace) {
2328 // Generate 50 backtraces, and then check to see that we haven't created 50 new tombstones.
2329 auto get_tombstone_timestamps = []() -> std::map<int, time_t> {
2330 std::map<int, time_t> result;
2331 for (int i = 0; i < 99; ++i) {
2332 std::string path = android::base::StringPrintf("/data/tombstones/tombstone_%02d", i);
2333 struct stat st;
2334 if (stat(path.c_str(), &st) == 0) {
2335 result[i] = st.st_mtim.tv_sec;
2336 }
2337 }
2338 return result;
2339 };
2340
2341 auto before = get_tombstone_timestamps();
2342 for (int i = 0; i < 50; ++i) {
2343 raise_debugger_signal(kDebuggerdNativeBacktrace);
2344 }
2345 auto after = get_tombstone_timestamps();
2346
2347 int diff = 0;
2348 for (int i = 0; i < 99; ++i) {
2349 if (after.count(i) == 0) {
2350 continue;
2351 }
2352 if (before.count(i) == 0) {
2353 ++diff;
2354 continue;
2355 }
2356 if (before[i] != after[i]) {
2357 ++diff;
2358 }
2359 }
2360
2361 // We can't be sure that nothing's crash looping in the background.
2362 // This should be good enough, though...
2363 ASSERT_LT(diff, 10) << "too many new tombstones; is something crashing in the background?";
2364}
Christopher Ferris481e8372019-07-15 17:13:24 -07002365
2366static __attribute__((__noinline__)) void overflow_stack(void* p) {
2367 void* buf[1];
2368 buf[0] = p;
2369 static volatile void* global = buf;
2370 if (global) {
2371 global = buf;
2372 overflow_stack(&buf);
2373 }
2374}
2375
2376TEST_F(CrasherTest, stack_overflow) {
2377 int intercept_result;
2378 unique_fd output_fd;
2379 StartProcess([]() { overflow_stack(nullptr); });
2380
2381 StartIntercept(&output_fd);
2382 FinishCrasher();
2383 AssertDeath(SIGSEGV);
2384 FinishIntercept(&intercept_result);
2385
2386 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2387
2388 std::string result;
2389 ConsumeFd(std::move(output_fd), &result);
2390 ASSERT_MATCH(result, R"(Cause: stack pointer[^\n]*stack overflow.\n)");
2391}
Josh Gao76e1e302021-01-26 15:53:11 -08002392
Christopher Ferris22035cc2023-01-31 17:50:22 -08002393static std::string GetTestLibraryPath() {
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002394 std::string test_lib(testing::internal::GetArgvs()[0]);
2395 auto const value = test_lib.find_last_of('/');
2396 if (value == std::string::npos) {
2397 test_lib = "./";
2398 } else {
2399 test_lib = test_lib.substr(0, value + 1) + "./";
2400 }
Christopher Ferris22035cc2023-01-31 17:50:22 -08002401 return test_lib + "libcrash_test.so";
2402}
2403
2404static void CreateEmbeddedLibrary(int out_fd) {
2405 std::string test_lib(GetTestLibraryPath());
2406 android::base::unique_fd fd(open(test_lib.c_str(), O_RDONLY | O_CLOEXEC));
2407 ASSERT_NE(fd.get(), -1);
2408 off_t file_size = lseek(fd, 0, SEEK_END);
2409 ASSERT_EQ(lseek(fd, 0, SEEK_SET), 0);
2410 std::vector<uint8_t> contents(file_size);
2411 ASSERT_TRUE(android::base::ReadFully(fd, contents.data(), contents.size()));
2412
2413 // Put the shared library data at a pagesize() offset.
2414 ASSERT_EQ(lseek(out_fd, 4 * getpagesize(), SEEK_CUR), 4 * getpagesize());
2415 ASSERT_EQ(static_cast<size_t>(write(out_fd, contents.data(), contents.size())), contents.size());
2416}
2417
2418TEST_F(CrasherTest, non_zero_offset_in_library) {
2419 int intercept_result;
2420 unique_fd output_fd;
2421 TemporaryFile tf;
2422 CreateEmbeddedLibrary(tf.fd);
2423 StartProcess([&tf]() {
2424 android_dlextinfo extinfo{};
2425 extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET;
2426 extinfo.library_fd = tf.fd;
2427 extinfo.library_fd_offset = 4 * getpagesize();
2428 void* handle = android_dlopen_ext(tf.path, RTLD_NOW, &extinfo);
2429 if (handle == nullptr) {
2430 _exit(1);
2431 }
2432 void (*crash_func)() = reinterpret_cast<void (*)()>(dlsym(handle, "crash"));
2433 if (crash_func == nullptr) {
2434 _exit(1);
2435 }
2436 crash_func();
2437 });
2438
2439 StartIntercept(&output_fd);
2440 FinishCrasher();
2441 AssertDeath(SIGSEGV);
2442 FinishIntercept(&intercept_result);
2443
2444 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2445
2446 std::string result;
2447 ConsumeFd(std::move(output_fd), &result);
2448
2449 // Verify the crash includes an offset value in the backtrace.
2450 std::string match_str = android::base::StringPrintf("%s\\!libcrash_test.so \\(offset 0x%x\\)",
2451 tf.path, 4 * getpagesize());
2452 ASSERT_MATCH(result, match_str);
2453}
2454
2455static bool CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) {
2456 std::string test_lib(GetTestLibraryPath());
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002457
2458 *tmp_so_name = std::string(tmp_dir) + "/libcrash_test.so";
2459 std::string cp_cmd = android::base::StringPrintf("cp %s %s", test_lib.c_str(), tmp_dir);
2460
2461 // Copy the shared so to a tempory directory.
2462 return system(cp_cmd.c_str()) == 0;
2463}
2464
2465TEST_F(CrasherTest, unreadable_elf) {
2466 int intercept_result;
2467 unique_fd output_fd;
Christopher Ferrisc95047d2022-03-14 15:02:11 -07002468 std::string tmp_so_name;
2469 StartProcess([&tmp_so_name]() {
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002470 TemporaryDir td;
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002471 if (!CopySharedLibrary(td.path, &tmp_so_name)) {
2472 _exit(1);
2473 }
2474 void* handle = dlopen(tmp_so_name.c_str(), RTLD_NOW);
2475 if (handle == nullptr) {
2476 _exit(1);
2477 }
2478 // Delete the original shared library so that we get the warning
2479 // about unreadable elf files.
2480 if (unlink(tmp_so_name.c_str()) == -1) {
2481 _exit(1);
2482 }
2483 void (*crash_func)() = reinterpret_cast<void (*)()>(dlsym(handle, "crash"));
2484 if (crash_func == nullptr) {
2485 _exit(1);
2486 }
2487 crash_func();
2488 });
2489
2490 StartIntercept(&output_fd);
2491 FinishCrasher();
2492 AssertDeath(SIGSEGV);
2493 FinishIntercept(&intercept_result);
2494
2495 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2496
2497 std::string result;
2498 ConsumeFd(std::move(output_fd), &result);
2499 ASSERT_MATCH(result, R"(NOTE: Function names and BuildId information is missing )");
Christopher Ferrisc95047d2022-03-14 15:02:11 -07002500 std::string match_str = "NOTE: " + tmp_so_name;
2501 ASSERT_MATCH(result, match_str);
Christopher Ferrisfe751c52021-04-16 09:40:40 -07002502}
2503
Christopher Ferris20f50ec2024-01-03 02:30:03 +00002504void CheckForTombstone(const struct stat& text_st, std::optional<std::string>& tombstone_file) {
2505 static std::regex tombstone_re("tombstone_\\d+");
Christopher Ferris35da2882021-02-17 15:39:06 -08002506 std::unique_ptr<DIR, decltype(&closedir)> dir_h(opendir("/data/tombstones"), closedir);
2507 ASSERT_TRUE(dir_h != nullptr);
Christopher Ferris35da2882021-02-17 15:39:06 -08002508 dirent* entry;
2509 while ((entry = readdir(dir_h.get())) != nullptr) {
2510 if (!std::regex_match(entry->d_name, tombstone_re)) {
2511 continue;
2512 }
2513 std::string path = android::base::StringPrintf("/data/tombstones/%s", entry->d_name);
Josh Gao76e1e302021-01-26 15:53:11 -08002514
2515 struct stat st;
2516 if (TEMP_FAILURE_RETRY(stat(path.c_str(), &st)) != 0) {
2517 continue;
2518 }
2519
2520 if (st.st_dev == text_st.st_dev && st.st_ino == text_st.st_ino) {
Christopher Ferris35da2882021-02-17 15:39:06 -08002521 tombstone_file = path;
Josh Gao76e1e302021-01-26 15:53:11 -08002522 break;
2523 }
2524 }
Christopher Ferris20f50ec2024-01-03 02:30:03 +00002525}
Josh Gao76e1e302021-01-26 15:53:11 -08002526
Christopher Ferris20f50ec2024-01-03 02:30:03 +00002527TEST(tombstoned, proto) {
2528 const pid_t self = getpid();
2529 unique_fd tombstoned_socket, text_fd, proto_fd;
2530 ASSERT_TRUE(
2531 tombstoned_connect(self, &tombstoned_socket, &text_fd, &proto_fd, kDebuggerdTombstoneProto));
2532
2533 tombstoned_notify_completion(tombstoned_socket.get());
2534
2535 ASSERT_NE(-1, text_fd.get());
2536 ASSERT_NE(-1, proto_fd.get());
2537
2538 struct stat text_st;
2539 ASSERT_EQ(0, fstat(text_fd.get(), &text_st));
2540
2541 std::optional<std::string> tombstone_file;
2542 // Allow up to 5 seconds for the tombstone to be written to the system.
2543 const auto max_wait_time = std::chrono::seconds(5) * android::base::HwTimeoutMultiplier();
2544 const auto start = std::chrono::high_resolution_clock::now();
2545 while (true) {
2546 std::this_thread::sleep_for(100ms);
2547 CheckForTombstone(text_st, tombstone_file);
2548 if (tombstone_file) {
2549 break;
2550 }
2551 if (std::chrono::high_resolution_clock::now() - start > max_wait_time) {
2552 break;
2553 }
2554 }
2555
2556 ASSERT_TRUE(tombstone_file) << "Timed out trying to find tombstone file.";
Christopher Ferris35da2882021-02-17 15:39:06 -08002557 std::string proto_path = tombstone_file.value() + ".pb";
Josh Gao76e1e302021-01-26 15:53:11 -08002558
2559 struct stat proto_fd_st;
2560 struct stat proto_file_st;
2561 ASSERT_EQ(0, fstat(proto_fd.get(), &proto_fd_st));
2562 ASSERT_EQ(0, stat(proto_path.c_str(), &proto_file_st));
2563
2564 ASSERT_EQ(proto_fd_st.st_dev, proto_file_st.st_dev);
2565 ASSERT_EQ(proto_fd_st.st_ino, proto_file_st.st_ino);
2566}
2567
2568TEST(tombstoned, proto_intercept) {
2569 const pid_t self = getpid();
2570 unique_fd intercept_fd, output_fd;
Josh Gao76e1e302021-01-26 15:53:11 -08002571
Christopher Ferrisb92b52c2023-10-16 19:14:28 -07002572 InterceptResponse response = {};
2573 tombstoned_intercept(self, &intercept_fd, &output_fd, &response, kDebuggerdTombstone);
2574 ASSERT_EQ(InterceptStatus::kRegistered, response.status)
2575 << "Error message: " << response.error_message;
Josh Gao76e1e302021-01-26 15:53:11 -08002576
2577 unique_fd tombstoned_socket, text_fd, proto_fd;
2578 ASSERT_TRUE(
2579 tombstoned_connect(self, &tombstoned_socket, &text_fd, &proto_fd, kDebuggerdTombstoneProto));
2580 ASSERT_TRUE(android::base::WriteStringToFd("foo", text_fd.get()));
2581 tombstoned_notify_completion(tombstoned_socket.get());
2582
2583 text_fd.reset();
2584
2585 std::string output;
2586 ASSERT_TRUE(android::base::ReadFdToString(output_fd, &output));
2587 ASSERT_EQ("foo", output);
2588}
Christopher Ferrisa3e9a0b2021-07-29 12:38:07 -07002589
2590// Verify that when an intercept is present for the main thread, and the signal
2591// is received on a different thread, the intercept still works.
2592TEST_F(CrasherTest, intercept_for_main_thread_signal_on_side_thread) {
2593 StartProcess([]() {
2594 std::thread thread([]() {
2595 // Raise the signal on the side thread.
2596 raise_debugger_signal(kDebuggerdNativeBacktrace);
2597 });
2598 thread.join();
2599 _exit(0);
2600 });
2601
2602 unique_fd output_fd;
2603 StartIntercept(&output_fd, kDebuggerdNativeBacktrace);
2604 FinishCrasher();
2605 AssertDeath(0);
2606
2607 int intercept_result;
2608 FinishIntercept(&intercept_result);
2609 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2610
2611 std::string result;
2612 ConsumeFd(std::move(output_fd), &result);
2613 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
2614}
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002615
2616static std::string format_pointer(uintptr_t ptr) {
2617#if defined(__LP64__)
2618 return android::base::StringPrintf("%08x'%08x", static_cast<uint32_t>(ptr >> 32),
2619 static_cast<uint32_t>(ptr & 0xffffffff));
2620#else
2621 return android::base::StringPrintf("%08x", static_cast<uint32_t>(ptr & 0xffffffff));
2622#endif
2623}
2624
2625static std::string format_pointer(void* ptr) {
2626 return format_pointer(reinterpret_cast<uintptr_t>(ptr));
2627}
2628
2629static std::string format_full_pointer(uintptr_t ptr) {
2630#if defined(__LP64__)
2631 return android::base::StringPrintf("%016" PRIx64, ptr);
2632#else
2633 return android::base::StringPrintf("%08x", ptr);
2634#endif
2635}
2636
2637static std::string format_full_pointer(void* ptr) {
2638 return format_full_pointer(reinterpret_cast<uintptr_t>(ptr));
2639}
2640
2641__attribute__((__noinline__)) int crash_call(uintptr_t ptr) {
2642 int* crash_ptr = reinterpret_cast<int*>(ptr);
2643 *crash_ptr = 1;
2644 return *crash_ptr;
2645}
2646
2647// Verify that a fault address before the first map is properly handled.
2648TEST_F(CrasherTest, fault_address_before_first_map) {
2649 StartProcess([]() {
2650 ASSERT_EQ(0, crash_call(0x1024));
2651 _exit(0);
2652 });
2653
2654 unique_fd output_fd;
2655 StartIntercept(&output_fd);
2656 FinishCrasher();
2657 AssertDeath(SIGSEGV);
2658
2659 int intercept_result;
2660 FinishIntercept(&intercept_result);
2661 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2662
2663 std::string result;
2664 ConsumeFd(std::move(output_fd), &result);
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002665 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+1024)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002666
2667 ASSERT_MATCH(result, R"(\nmemory map \(.*\):\n)");
2668
2669 std::string match_str = android::base::StringPrintf(
2670 R"(memory map .*:\n--->Fault address falls at %s before any mapped regions\n )",
2671 format_pointer(0x1024).c_str());
2672 ASSERT_MATCH(result, match_str);
2673}
2674
2675// Verify that a fault address after the last map is properly handled.
2676TEST_F(CrasherTest, fault_address_after_last_map) {
Florian Mayerb4979292022-04-15 14:35:17 -07002677 // This makes assumptions about the memory layout that are not true in HWASan
2678 // processes.
2679 SKIP_WITH_HWASAN;
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002680 uintptr_t crash_uptr = untag_address(UINTPTR_MAX - 15);
2681 StartProcess([crash_uptr]() {
2682 ASSERT_EQ(0, crash_call(crash_uptr));
2683 _exit(0);
2684 });
2685
2686 unique_fd output_fd;
2687 StartIntercept(&output_fd);
2688 FinishCrasher();
2689 AssertDeath(SIGSEGV);
2690
2691 int intercept_result;
2692 FinishIntercept(&intercept_result);
2693 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2694
2695 std::string result;
2696 ConsumeFd(std::move(output_fd), &result);
2697
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002698 std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x)";
2699 match_str += format_full_pointer(crash_uptr);
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002700 ASSERT_MATCH(result, match_str);
2701
Ryan Prichardbc227032024-02-29 14:40:57 -08002702 ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002703
Christopher Ferris3a0833c2023-07-28 13:07:53 -07002704 // Verifies that the fault address error message is at the end of the
2705 // maps section. To do this, the check below looks for the start of the
2706 // open files section or the start of the log file section. It's possible
2707 // for either of these sections to be present after the maps section right
2708 // now.
2709 // If the sections move around, this check might need to be modified.
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002710 match_str = android::base::StringPrintf(
Christopher Ferris3a0833c2023-07-28 13:07:53 -07002711 R"(\n--->Fault address falls at %s after any mapped regions\n(---------|\nopen files:))",
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002712 format_pointer(crash_uptr).c_str());
2713 ASSERT_MATCH(result, match_str);
2714}
2715
2716// Verify that a fault address between maps is properly handled.
2717TEST_F(CrasherTest, fault_address_between_maps) {
2718 // Create a map before the fork so it will be present in the child.
2719 void* start_ptr =
2720 mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2721 ASSERT_NE(MAP_FAILED, start_ptr);
2722 // Unmap the page in the middle.
2723 void* middle_ptr =
2724 reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start_ptr) + getpagesize());
2725 ASSERT_EQ(0, munmap(middle_ptr, getpagesize()));
2726
2727 StartProcess([middle_ptr]() {
2728 ASSERT_EQ(0, crash_call(reinterpret_cast<uintptr_t>(middle_ptr)));
2729 _exit(0);
2730 });
2731
2732 // Unmap the two maps.
2733 ASSERT_EQ(0, munmap(start_ptr, getpagesize()));
2734 void* end_ptr =
2735 reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start_ptr) + 2 * getpagesize());
2736 ASSERT_EQ(0, munmap(end_ptr, getpagesize()));
2737
2738 unique_fd output_fd;
2739 StartIntercept(&output_fd);
2740 FinishCrasher();
2741 AssertDeath(SIGSEGV);
2742
2743 int intercept_result;
2744 FinishIntercept(&intercept_result);
2745 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2746
2747 std::string result;
2748 ConsumeFd(std::move(output_fd), &result);
2749
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002750 std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x)";
2751 match_str += format_full_pointer(reinterpret_cast<uintptr_t>(middle_ptr));
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002752 ASSERT_MATCH(result, match_str);
2753
Ryan Prichardbc227032024-02-29 14:40:57 -08002754 ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002755
2756 match_str = android::base::StringPrintf(
2757 R"( %s.*\n--->Fault address falls at %s between mapped regions\n %s)",
2758 format_pointer(start_ptr).c_str(), format_pointer(middle_ptr).c_str(),
2759 format_pointer(end_ptr).c_str());
2760 ASSERT_MATCH(result, match_str);
2761}
2762
2763// Verify that a fault address happens in the correct map.
2764TEST_F(CrasherTest, fault_address_in_map) {
2765 // Create a map before the fork so it will be present in the child.
2766 void* ptr = mmap(nullptr, getpagesize(), 0, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2767 ASSERT_NE(MAP_FAILED, ptr);
2768
2769 StartProcess([ptr]() {
2770 ASSERT_EQ(0, crash_call(reinterpret_cast<uintptr_t>(ptr)));
2771 _exit(0);
2772 });
2773
2774 ASSERT_EQ(0, munmap(ptr, getpagesize()));
2775
2776 unique_fd output_fd;
2777 StartIntercept(&output_fd);
2778 FinishCrasher();
2779 AssertDeath(SIGSEGV);
2780
2781 int intercept_result;
2782 FinishIntercept(&intercept_result);
2783 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2784
2785 std::string result;
2786 ConsumeFd(std::move(output_fd), &result);
2787
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002788 std::string match_str = R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\), fault addr 0x)";
2789 match_str += format_full_pointer(reinterpret_cast<uintptr_t>(ptr));
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002790 ASSERT_MATCH(result, match_str);
2791
Ryan Prichardbc227032024-02-29 14:40:57 -08002792 ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
Christopher Ferris7e4c2a82021-08-20 17:45:09 -07002793
2794 match_str = android::base::StringPrintf(R"(\n--->%s.*\n)", format_pointer(ptr).c_str());
2795 ASSERT_MATCH(result, match_str);
2796}
Christopher Ferris2038cc72021-09-15 03:57:10 +00002797
2798static constexpr uint32_t kDexData[] = {
2799 0x0a786564, 0x00383330, 0xc98b3ab8, 0xf3749d94, 0xaecca4d8, 0xffc7b09a, 0xdca9ca7f, 0x5be5deab,
2800 0x00000220, 0x00000070, 0x12345678, 0x00000000, 0x00000000, 0x0000018c, 0x00000008, 0x00000070,
2801 0x00000004, 0x00000090, 0x00000002, 0x000000a0, 0x00000000, 0x00000000, 0x00000003, 0x000000b8,
2802 0x00000001, 0x000000d0, 0x00000130, 0x000000f0, 0x00000122, 0x0000012a, 0x00000132, 0x00000146,
2803 0x00000151, 0x00000154, 0x00000158, 0x0000016d, 0x00000001, 0x00000002, 0x00000004, 0x00000006,
2804 0x00000004, 0x00000002, 0x00000000, 0x00000005, 0x00000002, 0x0000011c, 0x00000000, 0x00000000,
2805 0x00010000, 0x00000007, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000,
2806 0x00000003, 0x00000000, 0x0000017e, 0x00000000, 0x00010001, 0x00000001, 0x00000173, 0x00000004,
2807 0x00021070, 0x000e0000, 0x00010001, 0x00000000, 0x00000178, 0x00000001, 0x0000000e, 0x00000001,
2808 0x3c060003, 0x74696e69, 0x4c06003e, 0x6e69614d, 0x4c12003b, 0x6176616a, 0x6e616c2f, 0x624f2f67,
2809 0x7463656a, 0x4d09003b, 0x2e6e6961, 0x6176616a, 0x00560100, 0x004c5602, 0x6a4c5b13, 0x2f617661,
2810 0x676e616c, 0x7274532f, 0x3b676e69, 0x616d0400, 0x01006e69, 0x000e0700, 0x07000103, 0x0000000e,
2811 0x81000002, 0x01f00480, 0x02880901, 0x0000000c, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
2812 0x00000008, 0x00000070, 0x00000002, 0x00000004, 0x00000090, 0x00000003, 0x00000002, 0x000000a0,
2813 0x00000005, 0x00000003, 0x000000b8, 0x00000006, 0x00000001, 0x000000d0, 0x00002001, 0x00000002,
2814 0x000000f0, 0x00001001, 0x00000001, 0x0000011c, 0x00002002, 0x00000008, 0x00000122, 0x00002003,
2815 0x00000002, 0x00000173, 0x00002000, 0x00000001, 0x0000017e, 0x00001000, 0x00000001, 0x0000018c,
2816};
2817
2818TEST_F(CrasherTest, verify_dex_pc_with_function_name) {
2819 StartProcess([]() {
2820 TemporaryDir td;
2821 std::string tmp_so_name;
2822 if (!CopySharedLibrary(td.path, &tmp_so_name)) {
2823 _exit(1);
2824 }
2825
2826 // In order to cause libunwindstack to look for this __dex_debug_descriptor
2827 // move the library to which has a basename of libart.so.
2828 std::string art_so_name = android::base::Dirname(tmp_so_name) + "/libart.so";
2829 ASSERT_EQ(0, rename(tmp_so_name.c_str(), art_so_name.c_str()));
2830 void* handle = dlopen(art_so_name.c_str(), RTLD_NOW | RTLD_LOCAL);
2831 if (handle == nullptr) {
2832 _exit(1);
2833 }
2834
2835 void* ptr =
2836 mmap(nullptr, sizeof(kDexData), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2837 ASSERT_TRUE(ptr != MAP_FAILED);
2838 memcpy(ptr, kDexData, sizeof(kDexData));
2839 prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, sizeof(kDexData), "dex");
2840
2841 JITCodeEntry dex_entry = {.symfile_addr = reinterpret_cast<uintptr_t>(ptr),
2842 .symfile_size = sizeof(kDexData)};
2843
2844 JITDescriptor* dex_debug =
2845 reinterpret_cast<JITDescriptor*>(dlsym(handle, "__dex_debug_descriptor"));
2846 ASSERT_TRUE(dex_debug != nullptr);
2847 dex_debug->version = 1;
2848 dex_debug->action_flag = 0;
2849 dex_debug->relevant_entry = 0;
2850 dex_debug->first_entry = reinterpret_cast<uintptr_t>(&dex_entry);
2851
2852 // This sets the magic dex pc value for register 0, using the value
2853 // of register 1 + 0x102.
2854 asm(".cfi_escape "
2855 "0x16 /* DW_CFA_val_expression */, 0, 0x0a /* size */,"
2856 "0x0c /* DW_OP_const4u */, 0x44, 0x45, 0x58, 0x31, /* magic = 'DEX1' */"
2857 "0x13 /* DW_OP_drop */,"
2858 "0x92 /* DW_OP_bregx */, 1, 0x82, 0x02 /* 2-byte SLEB128 */");
2859
2860 // For each different architecture, set register one to the dex ptr mmap
2861 // created above. Then do a nullptr dereference to force a crash.
2862#if defined(__arm__)
2863 asm volatile(
2864 "mov r1, %[base]\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002865 "mov r2, #0\n"
2866 "str r2, [r2]\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002867 : [base] "+r"(ptr)
2868 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002869 : "r1", "r2", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002870#elif defined(__aarch64__)
2871 asm volatile(
2872 "mov x1, %[base]\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002873 "mov x2, #0\n"
2874 "str xzr, [x2]\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002875 : [base] "+r"(ptr)
2876 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002877 : "x1", "x2", "memory");
2878#elif defined(__riscv)
2879 // TODO: x1 is ra (the link register) on riscv64, so this might have
2880 // unintended consequences, but we'll need to change the .cfi_escape if so.
2881 asm volatile(
2882 "mv x1, %[base]\n"
2883 "sw zero, 0(zero)\n"
2884 : [base] "+r"(ptr)
2885 :
2886 : "x1", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002887#elif defined(__i386__)
2888 asm volatile(
2889 "mov %[base], %%ecx\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002890 "movl $0, 0\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002891 : [base] "+r"(ptr)
2892 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002893 : "ecx", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002894#elif defined(__x86_64__)
2895 asm volatile(
2896 "mov %[base], %%rdx\n"
Elliott Hughes857e29c2023-03-20 15:48:30 -07002897 "movq $0, 0\n"
Christopher Ferris2038cc72021-09-15 03:57:10 +00002898 : [base] "+r"(ptr)
2899 :
Elliott Hughes857e29c2023-03-20 15:48:30 -07002900 : "rdx", "memory");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002901#else
2902#error "Unsupported architecture"
2903#endif
2904 _exit(0);
2905 });
2906
2907 unique_fd output_fd;
2908 StartIntercept(&output_fd);
2909 FinishCrasher();
2910 AssertDeath(SIGSEGV);
2911
2912 int intercept_result;
2913 FinishIntercept(&intercept_result);
2914 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2915
2916 std::string result;
2917 ConsumeFd(std::move(output_fd), &result);
2918
2919 // Verify the process crashed properly.
Peter Collingbourne773acaa2021-11-10 16:29:23 -08002920 ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0*)");
Christopher Ferris2038cc72021-09-15 03:57:10 +00002921
2922 // Now verify that the dex_pc frame includes a proper function name.
2923 ASSERT_MATCH(result, R"( \[anon:dex\] \(Main\.\<init\>\+2)");
2924}
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00002925
2926static std::string format_map_pointer(uintptr_t ptr) {
2927#if defined(__LP64__)
2928 return android::base::StringPrintf("%08x'%08x", static_cast<uint32_t>(ptr >> 32),
2929 static_cast<uint32_t>(ptr & 0xffffffff));
2930#else
2931 return android::base::StringPrintf("%08x", ptr);
2932#endif
2933}
2934
2935// Verify that map data is properly formatted.
2936TEST_F(CrasherTest, verify_map_format) {
2937 // Create multiple maps to make sure that the map data is formatted properly.
2938 void* none_map = mmap(nullptr, getpagesize(), 0, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2939 ASSERT_NE(MAP_FAILED, none_map);
2940 void* r_map = mmap(nullptr, getpagesize(), PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2941 ASSERT_NE(MAP_FAILED, r_map);
2942 void* w_map = mmap(nullptr, getpagesize(), PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2943 ASSERT_NE(MAP_FAILED, w_map);
2944 void* x_map = mmap(nullptr, getpagesize(), PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2945 ASSERT_NE(MAP_FAILED, x_map);
2946
2947 TemporaryFile tf;
2948 ASSERT_EQ(0x2000, lseek(tf.fd, 0x2000, SEEK_SET));
2949 char c = 'f';
2950 ASSERT_EQ(1, write(tf.fd, &c, 1));
2951 ASSERT_EQ(0x5000, lseek(tf.fd, 0x5000, SEEK_SET));
2952 ASSERT_EQ(1, write(tf.fd, &c, 1));
2953 ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
2954 void* file_map = mmap(nullptr, 0x3001, PROT_READ, MAP_PRIVATE, tf.fd, 0x2000);
2955 ASSERT_NE(MAP_FAILED, file_map);
2956
2957 StartProcess([]() { abort(); });
2958
2959 ASSERT_EQ(0, munmap(none_map, getpagesize()));
2960 ASSERT_EQ(0, munmap(r_map, getpagesize()));
2961 ASSERT_EQ(0, munmap(w_map, getpagesize()));
2962 ASSERT_EQ(0, munmap(x_map, getpagesize()));
2963 ASSERT_EQ(0, munmap(file_map, 0x3001));
2964
2965 unique_fd output_fd;
2966 StartIntercept(&output_fd);
2967 FinishCrasher();
2968 AssertDeath(SIGABRT);
2969 int intercept_result;
2970 FinishIntercept(&intercept_result);
2971
2972 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
2973
2974 std::string result;
2975 ConsumeFd(std::move(output_fd), &result);
2976
2977 std::string match_str;
2978 // Verify none.
2979 match_str = android::base::StringPrintf(
Christopher Ferris2f77c2a2024-05-07 12:25:31 -07002980 " %s-%s --- 0 %x\\n",
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00002981 format_map_pointer(reinterpret_cast<uintptr_t>(none_map)).c_str(),
Christopher Ferris2f77c2a2024-05-07 12:25:31 -07002982 format_map_pointer(reinterpret_cast<uintptr_t>(none_map) + getpagesize() - 1).c_str(),
2983 getpagesize());
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00002984 ASSERT_MATCH(result, match_str);
2985
2986 // Verify read-only.
2987 match_str = android::base::StringPrintf(
Christopher Ferris2f77c2a2024-05-07 12:25:31 -07002988 " %s-%s r-- 0 %x\\n",
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00002989 format_map_pointer(reinterpret_cast<uintptr_t>(r_map)).c_str(),
Christopher Ferris2f77c2a2024-05-07 12:25:31 -07002990 format_map_pointer(reinterpret_cast<uintptr_t>(r_map) + getpagesize() - 1).c_str(),
2991 getpagesize());
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00002992 ASSERT_MATCH(result, match_str);
2993
2994 // Verify write-only.
2995 match_str = android::base::StringPrintf(
Christopher Ferris2f77c2a2024-05-07 12:25:31 -07002996 " %s-%s -w- 0 %x\\n",
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00002997 format_map_pointer(reinterpret_cast<uintptr_t>(w_map)).c_str(),
Christopher Ferris2f77c2a2024-05-07 12:25:31 -07002998 format_map_pointer(reinterpret_cast<uintptr_t>(w_map) + getpagesize() - 1).c_str(),
2999 getpagesize());
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00003000 ASSERT_MATCH(result, match_str);
3001
3002 // Verify exec-only.
3003 match_str = android::base::StringPrintf(
Christopher Ferris2f77c2a2024-05-07 12:25:31 -07003004 " %s-%s --x 0 %x\\n",
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00003005 format_map_pointer(reinterpret_cast<uintptr_t>(x_map)).c_str(),
Christopher Ferris2f77c2a2024-05-07 12:25:31 -07003006 format_map_pointer(reinterpret_cast<uintptr_t>(x_map) + getpagesize() - 1).c_str(),
3007 getpagesize());
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00003008 ASSERT_MATCH(result, match_str);
3009
3010 // Verify file map with non-zero offset and a name.
3011 match_str = android::base::StringPrintf(
3012 " %s-%s r-- 2000 4000 %s\\n",
3013 format_map_pointer(reinterpret_cast<uintptr_t>(file_map)).c_str(),
3014 format_map_pointer(reinterpret_cast<uintptr_t>(file_map) + 0x3fff).c_str(), tf.path);
3015 ASSERT_MATCH(result, match_str);
3016}
3017
3018// Verify that the tombstone map data is correct.
3019TEST_F(CrasherTest, verify_header) {
3020 StartProcess([]() { abort(); });
3021
3022 unique_fd output_fd;
3023 StartIntercept(&output_fd);
3024 FinishCrasher();
3025 AssertDeath(SIGABRT);
3026 int intercept_result;
3027 FinishIntercept(&intercept_result);
3028
3029 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3030
3031 std::string result;
3032 ConsumeFd(std::move(output_fd), &result);
3033
3034 std::string match_str = android::base::StringPrintf(
3035 "Build fingerprint: '%s'\\nRevision: '%s'\\n",
3036 android::base::GetProperty("ro.build.fingerprint", "unknown").c_str(),
3037 android::base::GetProperty("ro.revision", "unknown").c_str());
3038 match_str += android::base::StringPrintf("ABI: '%s'\n", ABI_STRING);
3039 ASSERT_MATCH(result, match_str);
3040}
3041
3042// Verify that the thread header is formatted properly.
3043TEST_F(CrasherTest, verify_thread_header) {
3044 void* shared_map =
3045 mmap(nullptr, sizeof(pid_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
3046 ASSERT_NE(MAP_FAILED, shared_map);
3047 memset(shared_map, 0, sizeof(pid_t));
3048
3049 StartProcess([&shared_map]() {
3050 std::atomic_bool tid_written;
3051 std::thread thread([&tid_written, &shared_map]() {
3052 pid_t tid = gettid();
3053 memcpy(shared_map, &tid, sizeof(pid_t));
3054 tid_written = true;
3055 volatile bool done = false;
3056 while (!done)
3057 ;
3058 });
3059 thread.detach();
3060 while (!tid_written.load(std::memory_order_acquire))
3061 ;
3062 abort();
3063 });
3064
3065 pid_t primary_pid = crasher_pid;
3066
3067 unique_fd output_fd;
3068 StartIntercept(&output_fd);
3069 FinishCrasher();
3070 AssertDeath(SIGABRT);
3071 int intercept_result;
3072 FinishIntercept(&intercept_result);
3073 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3074
3075 // Read the tid data out.
3076 pid_t tid;
3077 memcpy(&tid, shared_map, sizeof(pid_t));
3078 ASSERT_NE(0, tid);
3079
3080 ASSERT_EQ(0, munmap(shared_map, sizeof(pid_t)));
3081
3082 std::string result;
3083 ConsumeFd(std::move(output_fd), &result);
3084
3085 // Verify that there are two headers, one where the tid is "primary_pid"
3086 // and the other where the tid is "tid".
3087 std::string match_str = android::base::StringPrintf("pid: %d, tid: %d, name: .* >>> .* <<<\\n",
3088 primary_pid, primary_pid);
3089 ASSERT_MATCH(result, match_str);
3090
3091 match_str =
3092 android::base::StringPrintf("pid: %d, tid: %d, name: .* >>> .* <<<\\n", primary_pid, tid);
3093 ASSERT_MATCH(result, match_str);
3094}
3095
3096// Verify that there is a BuildID present in the map section and set properly.
3097TEST_F(CrasherTest, verify_build_id) {
3098 StartProcess([]() { abort(); });
3099
3100 unique_fd output_fd;
3101 StartIntercept(&output_fd);
3102 FinishCrasher();
3103 AssertDeath(SIGABRT);
3104 int intercept_result;
3105 FinishIntercept(&intercept_result);
3106 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3107
3108 std::string result;
3109 ConsumeFd(std::move(output_fd), &result);
3110
3111 // Find every /system or /apex lib and verify the BuildID is displayed
3112 // properly.
3113 bool found_valid_elf = false;
3114 std::smatch match;
3115 std::regex build_id_regex(R"( ((/system/|/apex/)\S+) \(BuildId: ([^\)]+)\))");
3116 for (std::string prev_file; std::regex_search(result, match, build_id_regex);
3117 result = match.suffix()) {
3118 if (prev_file == match[1]) {
3119 // Already checked this file.
3120 continue;
3121 }
3122
3123 prev_file = match[1];
Christopher Ferris15038902023-11-10 00:05:49 -08003124 auto elf_memory = unwindstack::Memory::CreateFileMemory(prev_file, 0);
3125 unwindstack::Elf elf(elf_memory);
Christopher Ferrisbdea3bb2021-11-17 01:09:22 +00003126 if (!elf.Init() || !elf.valid()) {
3127 // Skipping invalid elf files.
3128 continue;
3129 }
3130 ASSERT_EQ(match[3], elf.GetPrintableBuildID());
3131
3132 found_valid_elf = true;
3133 }
3134 ASSERT_TRUE(found_valid_elf) << "Did not find any elf files with valid BuildIDs to check.";
3135}
Christopher Ferrisbda10642023-04-24 18:14:53 -07003136
3137const char kLogMessage[] = "Should not see this log message.";
3138
3139// Verify that the logd process does not read the log.
3140TEST_F(CrasherTest, logd_skips_reading_logs) {
3141 StartProcess([]() {
3142 pthread_setname_np(pthread_self(), "logd");
3143 LOG(INFO) << kLogMessage;
3144 abort();
3145 });
3146
3147 unique_fd output_fd;
3148 StartIntercept(&output_fd);
3149 FinishCrasher();
3150 AssertDeath(SIGABRT);
3151 int intercept_result;
3152 FinishIntercept(&intercept_result);
3153 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3154
3155 std::string result;
3156 ConsumeFd(std::move(output_fd), &result);
3157 // logd should not contain our log message.
3158 ASSERT_NOT_MATCH(result, kLogMessage);
3159}
3160
3161// Verify that the logd process does not read the log when the non-main
3162// thread crashes.
3163TEST_F(CrasherTest, logd_skips_reading_logs_not_main_thread) {
3164 StartProcess([]() {
3165 pthread_setname_np(pthread_self(), "logd");
3166 LOG(INFO) << kLogMessage;
3167
3168 std::thread thread([]() {
3169 pthread_setname_np(pthread_self(), "not_logd_thread");
3170 // Raise the signal on the side thread.
3171 raise_debugger_signal(kDebuggerdTombstone);
3172 });
3173 thread.join();
3174 _exit(0);
3175 });
3176
3177 unique_fd output_fd;
3178 StartIntercept(&output_fd, kDebuggerdTombstone);
3179 FinishCrasher();
3180 AssertDeath(0);
3181
3182 int intercept_result;
3183 FinishIntercept(&intercept_result);
3184 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3185
3186 std::string result;
3187 ConsumeFd(std::move(output_fd), &result);
3188 ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
3189 ASSERT_NOT_MATCH(result, kLogMessage);
3190}
Christopher Ferris98d62422023-05-24 20:01:10 +00003191
3192// Disable this test since there is a high liklihood that this would
3193// be flaky since it requires 500 messages being in the log.
3194TEST_F(CrasherTest, DISABLED_max_log_messages) {
3195 StartProcess([]() {
3196 for (size_t i = 0; i < 600; i++) {
3197 LOG(INFO) << "Message number " << i;
3198 }
3199 abort();
3200 });
3201
3202 unique_fd output_fd;
3203 StartIntercept(&output_fd);
3204 FinishCrasher();
3205 AssertDeath(SIGABRT);
3206 int intercept_result;
3207 FinishIntercept(&intercept_result);
3208 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3209
3210 std::string result;
3211 ConsumeFd(std::move(output_fd), &result);
3212 ASSERT_NOT_MATCH(result, "Message number 99");
3213 ASSERT_MATCH(result, "Message number 100");
3214 ASSERT_MATCH(result, "Message number 599");
3215}
3216
3217TEST_F(CrasherTest, log_with_newline) {
3218 StartProcess([]() {
3219 LOG(INFO) << "This line has a newline.\nThis is on the next line.";
3220 abort();
3221 });
3222
3223 unique_fd output_fd;
3224 StartIntercept(&output_fd);
3225 FinishCrasher();
3226 AssertDeath(SIGABRT);
3227 int intercept_result;
3228 FinishIntercept(&intercept_result);
3229 ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
3230
3231 std::string result;
3232 ConsumeFd(std::move(output_fd), &result);
3233 ASSERT_MATCH(result, ":\\s*This line has a newline.");
3234 ASSERT_MATCH(result, ":\\s*This is on the next line.");
3235}