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