1cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao/* 2cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * Copyright 2016, The Android Open Source Project 3cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * 4cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * Licensed under the Apache License, Version 2.0 (the "License"); 5cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * you may not use this file except in compliance with the License. 6cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * You may obtain a copy of the License at 7cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * 8cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * http://www.apache.org/licenses/LICENSE-2.0 9cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * 10cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * Unless required by applicable law or agreed to in writing, software 11cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * distributed under the License is distributed on an "AS IS" BASIS, 12cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * See the License for the specific language governing permissions and 14cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao * limitations under the License. 15cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao */ 16cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 17cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <err.h> 18cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <fcntl.h> 19cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <unistd.h> 20502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao#include <sys/capability.h> 21fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao#include <sys/prctl.h> 22cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <sys/types.h> 23cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 24cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <chrono> 25cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <regex> 26cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <thread> 27cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 28502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao#include <android/set_abort_message.h> 29502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 30cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <android-base/file.h> 31cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <android-base/logging.h> 3292abfb41f3c96272268c065029275b39297d82a7Josh Gao#include <android-base/macros.h> 33cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <android-base/parseint.h> 34cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <android-base/properties.h> 35cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <android-base/strings.h> 36cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <android-base/unique_fd.h> 37cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <cutils/sockets.h> 38cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <debuggerd/handler.h> 39cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <debuggerd/protocol.h> 40dd6187677114cc9f308342db159076a8b64b53f2Josh Gao#include <debuggerd/tombstoned.h> 41cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <debuggerd/util.h> 42cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#include <gtest/gtest.h> 43cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 44cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gaousing namespace std::chrono_literals; 45cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gaousing android::base::unique_fd; 46cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 47cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#if defined(__LP64__) 48cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#define ARCH_SUFFIX "64" 49cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#else 50cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#define ARCH_SUFFIX "" 51cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#endif 52cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 53cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gaoconstexpr char kWaitForGdbKey[] = "debug.debuggerd.wait_for_gdb"; 54cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 55cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#define TIMEOUT(seconds, expr) \ 56cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao [&]() { \ 57cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao struct sigaction old_sigaction; \ 58cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao struct sigaction new_sigaction = {}; \ 59cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao new_sigaction.sa_handler = [](int) {}; \ 60cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao if (sigaction(SIGALRM, &new_sigaction, &new_sigaction) != 0) { \ 61cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao err(1, "sigaction failed"); \ 62cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } \ 63cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao alarm(seconds); \ 64cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao auto value = expr; \ 65cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao int saved_errno = errno; \ 66cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao if (sigaction(SIGALRM, &old_sigaction, nullptr) != 0) { \ 67cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao err(1, "sigaction failed"); \ 68cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } \ 69cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao alarm(0); \ 70cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao errno = saved_errno; \ 71cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao return value; \ 72cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao }() 73cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 74cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao#define ASSERT_MATCH(str, pattern) \ 75cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao do { \ 76cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao std::regex r((pattern)); \ 77cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao if (!std::regex_search((str), r)) { \ 78cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FAIL() << "regex mismatch: expected " << (pattern) << " in: \n" << (str); \ 79cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } \ 80cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } while (0) 81cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 825fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao#define ASSERT_NOT_MATCH(str, pattern) \ 835fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao do { \ 845fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao std::regex r((pattern)); \ 855fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao if (std::regex_search((str), r)) { \ 865fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao FAIL() << "regex mismatch: expected to not find " << (pattern) << " in: \n" << (str); \ 875fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao } \ 885fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao } while (0) 895fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao 90df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gaostatic void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, unique_fd* output_fd) { 91df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao intercept_fd->reset(socket_local_client(kTombstonedInterceptSocketName, 92df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET)); 93df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao if (intercept_fd->get() == -1) { 94df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao FAIL() << "failed to contact tombstoned: " << strerror(errno); 95df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao } 96df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao 97df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao InterceptRequest req = {.pid = target_pid}; 98df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao 99df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao unique_fd output_pipe_write; 100df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao if (!Pipe(output_fd, &output_pipe_write)) { 101df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao FAIL() << "failed to create output pipe: " << strerror(errno); 102df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao } 103df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao 104df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao std::string pipe_size_str; 105df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao int pipe_buffer_size; 106df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao if (!android::base::ReadFileToString("/proc/sys/fs/pipe-max-size", &pipe_size_str)) { 107df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao FAIL() << "failed to read /proc/sys/fs/pipe-max-size: " << strerror(errno); 108df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao } 109df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao 110df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao pipe_size_str = android::base::Trim(pipe_size_str); 111df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao 112df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao if (!android::base::ParseInt(pipe_size_str.c_str(), &pipe_buffer_size, 0)) { 113df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao FAIL() << "failed to parse pipe max size"; 114df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao } 115df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao 116df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao if (fcntl(output_fd->get(), F_SETPIPE_SZ, pipe_buffer_size) != pipe_buffer_size) { 117df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao FAIL() << "failed to set pipe size: " << strerror(errno); 118df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao } 119df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao 120a1c9e943c0687a2fd1195033824d22600abbd51eJosh Gao ASSERT_GE(pipe_buffer_size, 1024 * 1024); 121a1c9e943c0687a2fd1195033824d22600abbd51eJosh Gao 122df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao if (send_fd(intercept_fd->get(), &req, sizeof(req), std::move(output_pipe_write)) != sizeof(req)) { 123df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao FAIL() << "failed to send output fd to tombstoned: " << strerror(errno); 124df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao } 125df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao 126df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao InterceptResponse response; 127df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao ssize_t rc = TEMP_FAILURE_RETRY(read(intercept_fd->get(), &response, sizeof(response))); 128df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao if (rc == -1) { 129df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao FAIL() << "failed to read response from tombstoned: " << strerror(errno); 130df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao } else if (rc == 0) { 131df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao FAIL() << "failed to read response from tombstoned (EOF)"; 132df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao } else if (rc != sizeof(response)) { 133df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao FAIL() << "received packet of unexpected length from tombstoned: expected " << sizeof(response) 134df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao << ", received " << rc; 135df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao } 136df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao 137df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao ASSERT_EQ(InterceptStatus::kRegistered, response.status); 138df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao} 139df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao 140cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gaoclass CrasherTest : public ::testing::Test { 141cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao public: 142cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao pid_t crasher_pid = -1; 143cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao bool previous_wait_for_gdb; 144cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao unique_fd crasher_pipe; 145cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao unique_fd intercept_fd; 146cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 147cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao CrasherTest(); 148cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ~CrasherTest(); 149cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 150cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao void StartIntercept(unique_fd* output_fd); 151cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 152cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao // Returns -1 if we fail to read a response from tombstoned, otherwise the received return code. 153cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao void FinishIntercept(int* result); 154cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 15592abfb41f3c96272268c065029275b39297d82a7Josh Gao void StartProcess(std::function<void()> function, std::function<pid_t()> forker = fork); 156cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao void StartCrasher(const std::string& crash_type); 157cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao void FinishCrasher(); 158cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao void AssertDeath(int signo); 159cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao}; 160cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 161cbe70cb0a8cb0171f3802273050e851a47b090edJosh GaoCrasherTest::CrasherTest() { 162cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao previous_wait_for_gdb = android::base::GetBoolProperty(kWaitForGdbKey, false); 163cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao android::base::SetProperty(kWaitForGdbKey, "0"); 164cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao} 165cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 166cbe70cb0a8cb0171f3802273050e851a47b090edJosh GaoCrasherTest::~CrasherTest() { 167cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao if (crasher_pid != -1) { 168cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao kill(crasher_pid, SIGKILL); 169cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao int status; 170cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao waitpid(crasher_pid, &status, WUNTRACED); 171cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } 172cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 173cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao android::base::SetProperty(kWaitForGdbKey, previous_wait_for_gdb ? "1" : "0"); 174cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao} 175cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 176cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gaovoid CrasherTest::StartIntercept(unique_fd* output_fd) { 177cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao if (crasher_pid == -1) { 178cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FAIL() << "crasher hasn't been started"; 179cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } 180cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 181df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao tombstoned_intercept(crasher_pid, &this->intercept_fd, output_fd); 182cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao} 183cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 184cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gaovoid CrasherTest::FinishIntercept(int* result) { 185cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao InterceptResponse response; 186cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 187cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao // Timeout for tombstoned intercept is 10 seconds. 188cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ssize_t rc = TIMEOUT(20, read(intercept_fd.get(), &response, sizeof(response))); 189cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao if (rc == -1) { 190cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FAIL() << "failed to read response from tombstoned: " << strerror(errno); 191cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } else if (rc == 0) { 192cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao *result = -1; 193cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } else if (rc != sizeof(response)) { 194cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FAIL() << "received packet of unexpected length from tombstoned: expected " << sizeof(response) 195cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao << ", received " << rc; 196cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } else { 197df8cb05498a510f5bff5b2eb7bd704e77bf5664eJosh Gao *result = response.status == InterceptStatus::kStarted ? 1 : 0; 198cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } 199cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao} 200cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 20192abfb41f3c96272268c065029275b39297d82a7Josh Gaovoid CrasherTest::StartProcess(std::function<void()> function, std::function<pid_t()> forker) { 202fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao unique_fd read_pipe; 203cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao unique_fd crasher_read_pipe; 204cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao if (!Pipe(&crasher_read_pipe, &crasher_pipe)) { 205cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FAIL() << "failed to create pipe: " << strerror(errno); 206cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } 207cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 20892abfb41f3c96272268c065029275b39297d82a7Josh Gao crasher_pid = forker(); 209cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao if (crasher_pid == -1) { 210cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FAIL() << "fork failed: " << strerror(errno); 211cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } else if (crasher_pid == 0) { 212502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao char dummy; 213502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao crasher_pipe.reset(); 214502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao TEMP_FAILURE_RETRY(read(crasher_read_pipe.get(), &dummy, 1)); 215fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao function(); 216fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao _exit(0); 217fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao } 218fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao} 219fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao 220cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gaovoid CrasherTest::FinishCrasher() { 221cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao if (crasher_pipe == -1) { 222cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FAIL() << "crasher pipe uninitialized"; 223cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } 224cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 225cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ssize_t rc = write(crasher_pipe.get(), "\n", 1); 226cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao if (rc == -1) { 227cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FAIL() << "failed to write to crasher pipe: " << strerror(errno); 228cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } else if (rc == 0) { 229cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FAIL() << "crasher pipe was closed"; 230cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } 231cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao} 232cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 233cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gaovoid CrasherTest::AssertDeath(int signo) { 234cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao int status; 235cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao pid_t pid = TIMEOUT(5, waitpid(crasher_pid, &status, 0)); 236cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao if (pid != crasher_pid) { 237cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FAIL() << "failed to wait for crasher: " << strerror(errno); 238cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } 239cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 2405fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao if (signo == 0) { 2415fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao ASSERT_TRUE(WIFEXITED(status)); 2425fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao ASSERT_EQ(0, WEXITSTATUS(signo)); 2435fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao } else { 2445fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao ASSERT_FALSE(WIFEXITED(status)); 2455fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao ASSERT_TRUE(WIFSIGNALED(status)) << "crasher didn't terminate via a signal"; 2465fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao ASSERT_EQ(signo, WTERMSIG(status)); 247cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } 248cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao crasher_pid = -1; 249cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao} 250cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 251cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gaostatic void ConsumeFd(unique_fd fd, std::string* output) { 252cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao constexpr size_t read_length = PAGE_SIZE; 253cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao std::string result; 254cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 255cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao while (true) { 256cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao size_t offset = result.size(); 257cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao result.resize(result.size() + PAGE_SIZE); 258cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ssize_t rc = TEMP_FAILURE_RETRY(read(fd.get(), &result[offset], read_length)); 259cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao if (rc == -1) { 260cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FAIL() << "read failed: " << strerror(errno); 261cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } else if (rc == 0) { 262cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao result.resize(result.size() - PAGE_SIZE); 263cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao break; 264cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } 265cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 266cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao result.resize(result.size() - PAGE_SIZE + rc); 267cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } 268cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 269cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao *output = std::move(result); 270cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao} 271cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 272cbe70cb0a8cb0171f3802273050e851a47b090edJosh GaoTEST_F(CrasherTest, smoke) { 273cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao int intercept_result; 274cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao unique_fd output_fd; 275502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao StartProcess([]() { 276502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao *reinterpret_cast<volatile char*>(0xdead) = '1'; 277502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao }); 278502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 279cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao StartIntercept(&output_fd); 280cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FinishCrasher(); 281cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao AssertDeath(SIGSEGV); 282cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FinishIntercept(&intercept_result); 283cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 284cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; 285cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 286cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao std::string result; 287cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ConsumeFd(std::move(output_fd), &result); 288cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0xdead)"); 289cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao} 290cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 291cbe70cb0a8cb0171f3802273050e851a47b090edJosh GaoTEST_F(CrasherTest, abort) { 292cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao int intercept_result; 293cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao unique_fd output_fd; 294502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao StartProcess([]() { 295502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao abort(); 296502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao }); 297cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao StartIntercept(&output_fd); 298cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FinishCrasher(); 299cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao AssertDeath(SIGABRT); 300cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FinishIntercept(&intercept_result); 301cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 302cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; 303cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 304cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao std::string result; 305cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ConsumeFd(std::move(output_fd), &result); 306cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)"); 307cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao} 308cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 309cbe70cb0a8cb0171f3802273050e851a47b090edJosh GaoTEST_F(CrasherTest, signal) { 310cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao int intercept_result; 311cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao unique_fd output_fd; 312502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao StartProcess([]() { 313502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao abort(); 314502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao }); 315cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao StartIntercept(&output_fd); 316cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 317cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao // Wait for a bit, or we might end up killing the process before the signal 318cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao // handler even gets a chance to be registered. 319cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao std::this_thread::sleep_for(100ms); 320cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_EQ(0, kill(crasher_pid, SIGSEGV)); 321cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 322cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao AssertDeath(SIGSEGV); 323cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FinishIntercept(&intercept_result); 324cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 325cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; 326cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 327cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao std::string result; 328cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ConsumeFd(std::move(output_fd), &result); 329cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 0 \(SI_USER\), fault addr --------)"); 330cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_MATCH(result, R"(backtrace:)"); 331cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao} 332cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 333cbe70cb0a8cb0171f3802273050e851a47b090edJosh GaoTEST_F(CrasherTest, abort_message) { 334cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao int intercept_result; 335cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao unique_fd output_fd; 336502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao StartProcess([]() { 337502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao android_set_abort_message("abort message goes here"); 338502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao abort(); 339502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao }); 340cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao StartIntercept(&output_fd); 341cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FinishCrasher(); 342cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao AssertDeath(SIGABRT); 343cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FinishIntercept(&intercept_result); 344cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 345cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; 346cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 347cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao std::string result; 348cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ConsumeFd(std::move(output_fd), &result); 349502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao ASSERT_MATCH(result, R"(Abort message: 'abort message goes here')"); 350cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao} 351cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 3525fd02a8dbc44964018a7375ab1195e3c0c89919aJosh GaoTEST_F(CrasherTest, abort_message_backtrace) { 3535fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao int intercept_result; 3545fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao unique_fd output_fd; 3555fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao StartProcess([]() { 3565fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao android_set_abort_message("not actually aborting"); 3575fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao raise(DEBUGGER_SIGNAL); 3585fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao exit(0); 3595fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao }); 3605fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao StartIntercept(&output_fd); 3615fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao FinishCrasher(); 3625fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao AssertDeath(0); 3635fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao FinishIntercept(&intercept_result); 3645fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao 3655fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; 3665fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao 3675fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao std::string result; 3685fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao ConsumeFd(std::move(output_fd), &result); 3695fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao ASSERT_NOT_MATCH(result, R"(Abort message:)"); 3705fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao} 3715fd02a8dbc44964018a7375ab1195e3c0c89919aJosh Gao 372cbe70cb0a8cb0171f3802273050e851a47b090edJosh GaoTEST_F(CrasherTest, intercept_timeout) { 373cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao int intercept_result; 374cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao unique_fd output_fd; 375502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao StartProcess([]() { 376502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao abort(); 377502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao }); 378cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao StartIntercept(&output_fd); 379cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 380cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao // Don't let crasher finish until we timeout. 381cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FinishIntercept(&intercept_result); 382cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 383cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_NE(1, intercept_result) << "tombstoned reported success? (intercept_result = " 384cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao << intercept_result << ")"; 385cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 386cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FinishCrasher(); 387cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao AssertDeath(SIGABRT); 388cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao} 389cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 390cbe70cb0a8cb0171f3802273050e851a47b090edJosh GaoTEST_F(CrasherTest, wait_for_gdb) { 391cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao if (!android::base::SetProperty(kWaitForGdbKey, "1")) { 392cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FAIL() << "failed to enable wait_for_gdb"; 393cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } 394cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao sleep(1); 395cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 396502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao StartProcess([]() { 397502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao abort(); 398502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao }); 399cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FinishCrasher(); 400cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 401cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao int status; 402cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_EQ(crasher_pid, waitpid(crasher_pid, &status, WUNTRACED)); 403cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_TRUE(WIFSTOPPED(status)); 404cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_EQ(SIGSTOP, WSTOPSIG(status)); 405cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 406cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_EQ(0, kill(crasher_pid, SIGCONT)); 407cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 408cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao AssertDeath(SIGABRT); 409cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao} 410cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 4117c6e3133f57b6c908e211c0013fcb68d5a44d919Josh Gao// wait_for_gdb shouldn't trigger on manually sent signals. 412cbe70cb0a8cb0171f3802273050e851a47b090edJosh GaoTEST_F(CrasherTest, wait_for_gdb_signal) { 413cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao if (!android::base::SetProperty(kWaitForGdbKey, "1")) { 414cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FAIL() << "failed to enable wait_for_gdb"; 415cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao } 416cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 417502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao StartProcess([]() { 418502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao abort(); 419502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao }); 4207c6e3133f57b6c908e211c0013fcb68d5a44d919Josh Gao ASSERT_EQ(0, kill(crasher_pid, SIGSEGV)) << strerror(errno); 4217c6e3133f57b6c908e211c0013fcb68d5a44d919Josh Gao AssertDeath(SIGSEGV); 422cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao} 423cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 424cbe70cb0a8cb0171f3802273050e851a47b090edJosh GaoTEST_F(CrasherTest, backtrace) { 425cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao std::string result; 426cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao int intercept_result; 427cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao unique_fd output_fd; 428502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 429502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao StartProcess([]() { 430502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao abort(); 431502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao }); 432cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao StartIntercept(&output_fd); 433cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 434cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao std::this_thread::sleep_for(500ms); 435cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 436cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao sigval val; 437cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao val.sival_int = 1; 438cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_EQ(0, sigqueue(crasher_pid, DEBUGGER_SIGNAL, val)) << strerror(errno); 439cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FinishIntercept(&intercept_result); 440cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; 441cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ConsumeFd(std::move(output_fd), &result); 442cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(read\+)"); 443cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 444cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao int status; 445cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_EQ(0, waitpid(crasher_pid, &status, WNOHANG | WUNTRACED)); 446cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao 447cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao StartIntercept(&output_fd); 448cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FinishCrasher(); 449cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao AssertDeath(SIGABRT); 450cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao FinishIntercept(&intercept_result); 451cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; 452cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ConsumeFd(std::move(output_fd), &result); 453cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)"); 454cbe70cb0a8cb0171f3802273050e851a47b090edJosh Gao} 455fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao 456fca7ca35850438230428a0018d7b933f7c8a847cJosh GaoTEST_F(CrasherTest, PR_SET_DUMPABLE_0_crash) { 457502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao int intercept_result; 458502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao unique_fd output_fd; 459fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao StartProcess([]() { 460fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao prctl(PR_SET_DUMPABLE, 0); 461502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao abort(); 462fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao }); 463502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 464502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao StartIntercept(&output_fd); 465502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao FinishCrasher(); 466502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao AssertDeath(SIGABRT); 467502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao FinishIntercept(&intercept_result); 468502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 469502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; 470502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 471502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao std::string result; 472502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao ConsumeFd(std::move(output_fd), &result); 473502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)"); 474fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao} 475fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao 476502cfd22ba0e7bb4f8276438125a959547226f0aJosh GaoTEST_F(CrasherTest, capabilities) { 477502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao ASSERT_EQ(0U, getuid()) << "capability test requires root"; 478502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 479fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao StartProcess([]() { 480502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) { 481502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao err(1, "failed to set PR_SET_KEEPCAPS"); 482502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao } 483502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 484502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao if (setresuid(1, 1, 1) != 0) { 485502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao err(1, "setresuid failed"); 486502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao } 487502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 488502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao __user_cap_header_struct capheader; 489502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao __user_cap_data_struct capdata[2]; 490502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao memset(&capheader, 0, sizeof(capheader)); 491502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao memset(&capdata, 0, sizeof(capdata)); 492502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 493502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao capheader.version = _LINUX_CAPABILITY_VERSION_3; 494502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao capheader.pid = 0; 495502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 496502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao // Turn on every third capability. 497502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao static_assert(CAP_LAST_CAP > 33, "CAP_LAST_CAP <= 32"); 498502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao for (int i = 0; i < CAP_LAST_CAP; i += 3) { 499502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao capdata[CAP_TO_INDEX(i)].permitted |= CAP_TO_MASK(i); 500502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao capdata[CAP_TO_INDEX(i)].effective |= CAP_TO_MASK(i); 501502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao } 502502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 503502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao // Make sure CAP_SYS_PTRACE is off. 504502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao capdata[CAP_TO_INDEX(CAP_SYS_PTRACE)].permitted &= ~(CAP_TO_MASK(CAP_SYS_PTRACE)); 505502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao capdata[CAP_TO_INDEX(CAP_SYS_PTRACE)].effective &= ~(CAP_TO_MASK(CAP_SYS_PTRACE)); 506502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 507502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao if (capset(&capheader, &capdata[0]) != 0) { 508502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao err(1, "capset failed"); 509502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao } 510502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 511502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0) != 0) { 512502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao err(1, "failed to drop ambient capabilities"); 513502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao } 514502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 515845a2f9b4aa5b7f4742e1649bb74a2857d6492d4Josh Gao pthread_setname_np(pthread_self(), "thread_name"); 516502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao raise(SIGSYS); 517fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao }); 518502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 519502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao unique_fd output_fd; 520502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao StartIntercept(&output_fd); 521502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao FinishCrasher(); 522502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao AssertDeath(SIGSYS); 523502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao 524502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao std::string result; 525502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao int intercept_result; 526502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao FinishIntercept(&intercept_result); 527502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; 528502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao ConsumeFd(std::move(output_fd), &result); 529845a2f9b4aa5b7f4742e1649bb74a2857d6492d4Josh Gao ASSERT_MATCH(result, R"(name: thread_name\s+>>> .+debuggerd_test(32|64) <<<)"); 530502cfd22ba0e7bb4f8276438125a959547226f0aJosh Gao ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)"); 531fca7ca35850438230428a0018d7b933f7c8a847cJosh Gao} 532c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao 53392abfb41f3c96272268c065029275b39297d82a7Josh GaoTEST_F(CrasherTest, fake_pid) { 53492abfb41f3c96272268c065029275b39297d82a7Josh Gao int intercept_result; 53592abfb41f3c96272268c065029275b39297d82a7Josh Gao unique_fd output_fd; 53692abfb41f3c96272268c065029275b39297d82a7Josh Gao 53792abfb41f3c96272268c065029275b39297d82a7Josh Gao // Prime the getpid/gettid caches. 53892abfb41f3c96272268c065029275b39297d82a7Josh Gao UNUSED(getpid()); 53992abfb41f3c96272268c065029275b39297d82a7Josh Gao UNUSED(gettid()); 54092abfb41f3c96272268c065029275b39297d82a7Josh Gao 54192abfb41f3c96272268c065029275b39297d82a7Josh Gao std::function<pid_t()> clone_fn = []() { 54292abfb41f3c96272268c065029275b39297d82a7Josh Gao return syscall(__NR_clone, SIGCHLD, nullptr, nullptr, nullptr, nullptr); 54392abfb41f3c96272268c065029275b39297d82a7Josh Gao }; 54492abfb41f3c96272268c065029275b39297d82a7Josh Gao StartProcess( 54592abfb41f3c96272268c065029275b39297d82a7Josh Gao []() { 54692abfb41f3c96272268c065029275b39297d82a7Josh Gao ASSERT_NE(getpid(), syscall(__NR_getpid)); 54792abfb41f3c96272268c065029275b39297d82a7Josh Gao ASSERT_NE(gettid(), syscall(__NR_gettid)); 54892abfb41f3c96272268c065029275b39297d82a7Josh Gao raise(SIGSEGV); 54992abfb41f3c96272268c065029275b39297d82a7Josh Gao }, 55092abfb41f3c96272268c065029275b39297d82a7Josh Gao clone_fn); 55192abfb41f3c96272268c065029275b39297d82a7Josh Gao 55292abfb41f3c96272268c065029275b39297d82a7Josh Gao StartIntercept(&output_fd); 55392abfb41f3c96272268c065029275b39297d82a7Josh Gao FinishCrasher(); 55492abfb41f3c96272268c065029275b39297d82a7Josh Gao AssertDeath(SIGSEGV); 55592abfb41f3c96272268c065029275b39297d82a7Josh Gao FinishIntercept(&intercept_result); 55692abfb41f3c96272268c065029275b39297d82a7Josh Gao 55792abfb41f3c96272268c065029275b39297d82a7Josh Gao ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; 55892abfb41f3c96272268c065029275b39297d82a7Josh Gao 55992abfb41f3c96272268c065029275b39297d82a7Josh Gao std::string result; 56092abfb41f3c96272268c065029275b39297d82a7Josh Gao ConsumeFd(std::move(output_fd), &result); 56192abfb41f3c96272268c065029275b39297d82a7Josh Gao ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)"); 56292abfb41f3c96272268c065029275b39297d82a7Josh Gao} 56392abfb41f3c96272268c065029275b39297d82a7Josh Gao 564c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh GaoTEST(crash_dump, zombie) { 565c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao pid_t forkpid = fork(); 566c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao 567c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao pid_t rc; 568c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao int status; 569c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao 570c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao if (forkpid == 0) { 571c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao errno = 0; 572c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao rc = waitpid(-1, &status, WNOHANG | __WALL | __WNOTHREAD); 573c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao if (rc != -1 || errno != ECHILD) { 574c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao errx(2, "first waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno)); 575c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao } 576c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao 577c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao raise(DEBUGGER_SIGNAL); 578c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao 579c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao errno = 0; 580c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao rc = waitpid(-1, &status, __WALL | __WNOTHREAD); 581c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao if (rc != -1 || errno != ECHILD) { 582c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao errx(2, "second waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno)); 583c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao } 584c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao _exit(0); 585c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao } else { 586c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao rc = waitpid(forkpid, &status, 0); 587c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao ASSERT_EQ(forkpid, rc); 588c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao ASSERT_TRUE(WIFEXITED(status)); 589c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao ASSERT_EQ(0, WEXITSTATUS(status)); 590c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao } 591c3c8c029ecc46aa5d9fe6a5ee7c77c8adc5b23b5Josh Gao} 592dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 593dd6187677114cc9f308342db159076a8b64b53f2Josh GaoTEST(tombstoned, no_notify) { 594dd6187677114cc9f308342db159076a8b64b53f2Josh Gao // Do this a few times. 595dd6187677114cc9f308342db159076a8b64b53f2Josh Gao for (int i = 0; i < 3; ++i) { 596dd6187677114cc9f308342db159076a8b64b53f2Josh Gao pid_t pid = 123'456'789 + i; 597dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 598dd6187677114cc9f308342db159076a8b64b53f2Josh Gao unique_fd intercept_fd, output_fd; 599dd6187677114cc9f308342db159076a8b64b53f2Josh Gao tombstoned_intercept(pid, &intercept_fd, &output_fd); 600dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 601dd6187677114cc9f308342db159076a8b64b53f2Josh Gao { 602dd6187677114cc9f308342db159076a8b64b53f2Josh Gao unique_fd tombstoned_socket, input_fd; 603dd6187677114cc9f308342db159076a8b64b53f2Josh Gao ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd)); 604dd6187677114cc9f308342db159076a8b64b53f2Josh Gao ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid))); 605dd6187677114cc9f308342db159076a8b64b53f2Josh Gao } 606dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 607dd6187677114cc9f308342db159076a8b64b53f2Josh Gao pid_t read_pid; 608dd6187677114cc9f308342db159076a8b64b53f2Josh Gao ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid))); 609dd6187677114cc9f308342db159076a8b64b53f2Josh Gao ASSERT_EQ(read_pid, pid); 610dd6187677114cc9f308342db159076a8b64b53f2Josh Gao } 611dd6187677114cc9f308342db159076a8b64b53f2Josh Gao} 612dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 613dd6187677114cc9f308342db159076a8b64b53f2Josh GaoTEST(tombstoned, stress) { 614dd6187677114cc9f308342db159076a8b64b53f2Josh Gao // Spawn threads to simultaneously do a bunch of failing dumps and a bunch of successful dumps. 615dd6187677114cc9f308342db159076a8b64b53f2Josh Gao static constexpr int kDumpCount = 100; 616dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 617dd6187677114cc9f308342db159076a8b64b53f2Josh Gao std::atomic<bool> start(false); 618dd6187677114cc9f308342db159076a8b64b53f2Josh Gao std::vector<std::thread> threads; 619dd6187677114cc9f308342db159076a8b64b53f2Josh Gao threads.emplace_back([&start]() { 620dd6187677114cc9f308342db159076a8b64b53f2Josh Gao while (!start) { 621dd6187677114cc9f308342db159076a8b64b53f2Josh Gao continue; 622dd6187677114cc9f308342db159076a8b64b53f2Josh Gao } 623dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 624dd6187677114cc9f308342db159076a8b64b53f2Josh Gao // Use a way out of range pid, to avoid stomping on an actual process. 625dd6187677114cc9f308342db159076a8b64b53f2Josh Gao pid_t pid_base = 1'000'000; 626dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 627dd6187677114cc9f308342db159076a8b64b53f2Josh Gao for (int dump = 0; dump < kDumpCount; ++dump) { 628dd6187677114cc9f308342db159076a8b64b53f2Josh Gao pid_t pid = pid_base + dump; 629dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 630dd6187677114cc9f308342db159076a8b64b53f2Josh Gao unique_fd intercept_fd, output_fd; 631dd6187677114cc9f308342db159076a8b64b53f2Josh Gao tombstoned_intercept(pid, &intercept_fd, &output_fd); 632dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 633dd6187677114cc9f308342db159076a8b64b53f2Josh Gao // Pretend to crash, and then immediately close the socket. 634dd6187677114cc9f308342db159076a8b64b53f2Josh Gao unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName, 635dd6187677114cc9f308342db159076a8b64b53f2Josh Gao ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET)); 636dd6187677114cc9f308342db159076a8b64b53f2Josh Gao if (sockfd == -1) { 637dd6187677114cc9f308342db159076a8b64b53f2Josh Gao FAIL() << "failed to connect to tombstoned: " << strerror(errno); 638dd6187677114cc9f308342db159076a8b64b53f2Josh Gao } 639dd6187677114cc9f308342db159076a8b64b53f2Josh Gao TombstonedCrashPacket packet = {}; 640dd6187677114cc9f308342db159076a8b64b53f2Josh Gao packet.packet_type = CrashPacketType::kDumpRequest; 641dd6187677114cc9f308342db159076a8b64b53f2Josh Gao packet.packet.dump_request.pid = pid; 642dd6187677114cc9f308342db159076a8b64b53f2Josh Gao if (TEMP_FAILURE_RETRY(write(sockfd, &packet, sizeof(packet))) != sizeof(packet)) { 643dd6187677114cc9f308342db159076a8b64b53f2Josh Gao FAIL() << "failed to write to tombstoned: " << strerror(errno); 644dd6187677114cc9f308342db159076a8b64b53f2Josh Gao } 645dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 646dd6187677114cc9f308342db159076a8b64b53f2Josh Gao continue; 647dd6187677114cc9f308342db159076a8b64b53f2Josh Gao } 648dd6187677114cc9f308342db159076a8b64b53f2Josh Gao }); 649dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 650dd6187677114cc9f308342db159076a8b64b53f2Josh Gao threads.emplace_back([&start]() { 651dd6187677114cc9f308342db159076a8b64b53f2Josh Gao while (!start) { 652dd6187677114cc9f308342db159076a8b64b53f2Josh Gao continue; 653dd6187677114cc9f308342db159076a8b64b53f2Josh Gao } 654dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 655dd6187677114cc9f308342db159076a8b64b53f2Josh Gao // Use a way out of range pid, to avoid stomping on an actual process. 656dd6187677114cc9f308342db159076a8b64b53f2Josh Gao pid_t pid_base = 2'000'000; 657dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 658dd6187677114cc9f308342db159076a8b64b53f2Josh Gao for (int dump = 0; dump < kDumpCount; ++dump) { 659dd6187677114cc9f308342db159076a8b64b53f2Josh Gao pid_t pid = pid_base + dump; 660dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 661dd6187677114cc9f308342db159076a8b64b53f2Josh Gao unique_fd intercept_fd, output_fd; 662dd6187677114cc9f308342db159076a8b64b53f2Josh Gao tombstoned_intercept(pid, &intercept_fd, &output_fd); 663dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 664dd6187677114cc9f308342db159076a8b64b53f2Josh Gao { 665dd6187677114cc9f308342db159076a8b64b53f2Josh Gao unique_fd tombstoned_socket, input_fd; 666dd6187677114cc9f308342db159076a8b64b53f2Josh Gao ASSERT_TRUE(tombstoned_connect(pid, &tombstoned_socket, &input_fd)); 667dd6187677114cc9f308342db159076a8b64b53f2Josh Gao ASSERT_TRUE(android::base::WriteFully(input_fd.get(), &pid, sizeof(pid))); 668dd6187677114cc9f308342db159076a8b64b53f2Josh Gao tombstoned_notify_completion(tombstoned_socket.get()); 669dd6187677114cc9f308342db159076a8b64b53f2Josh Gao } 670dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 671dd6187677114cc9f308342db159076a8b64b53f2Josh Gao // TODO: Fix the race that requires this sleep. 672dd6187677114cc9f308342db159076a8b64b53f2Josh Gao std::this_thread::sleep_for(50ms); 673dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 674dd6187677114cc9f308342db159076a8b64b53f2Josh Gao pid_t read_pid; 675dd6187677114cc9f308342db159076a8b64b53f2Josh Gao ASSERT_TRUE(android::base::ReadFully(output_fd.get(), &read_pid, sizeof(read_pid))); 676dd6187677114cc9f308342db159076a8b64b53f2Josh Gao ASSERT_EQ(read_pid, pid); 677dd6187677114cc9f308342db159076a8b64b53f2Josh Gao } 678dd6187677114cc9f308342db159076a8b64b53f2Josh Gao }); 679dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 680dd6187677114cc9f308342db159076a8b64b53f2Josh Gao start = true; 681dd6187677114cc9f308342db159076a8b64b53f2Josh Gao 682dd6187677114cc9f308342db159076a8b64b53f2Josh Gao for (std::thread& thread : threads) { 683dd6187677114cc9f308342db159076a8b64b53f2Josh Gao thread.join(); 684dd6187677114cc9f308342db159076a8b64b53f2Josh Gao } 685dd6187677114cc9f308342db159076a8b64b53f2Josh Gao} 686