Loading debuggerd/crash_dump.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -79,9 +79,27 @@ static bool pid_contains_tid(int pid_proc_fd, pid_t tid) { return fstatat(pid_proc_fd, task_path.c_str(), &st, 0) == 0; } static pid_t get_tracer(pid_t tracee) { // Check to see if the thread is being ptraced by another process. android::procinfo::ProcessInfo process_info; if (android::procinfo::GetProcessInfo(tracee, &process_info)) { return process_info.tracer; } return -1; } // Attach to a thread, and verify that it's still a member of the given process static bool ptrace_seize_thread(int pid_proc_fd, pid_t tid, std::string* error) { if (ptrace(PTRACE_SEIZE, tid, 0, 0) != 0) { if (errno == EPERM) { pid_t tracer = get_tracer(tid); if (tracer != -1) { *error = StringPrintf("failed to attach to thread %d, already traced by %d (%s)", tid, tracer, get_process_name(tracer).c_str()); return false; } } *error = StringPrintf("failed to attach to thread %d: %s", tid, strerror(errno)); return false; } Loading debuggerd/debuggerd_test.cpp +36 −1 Original line number Diff line number Diff line Loading @@ -16,10 +16,11 @@ #include <err.h> #include <fcntl.h> #include <unistd.h> #include <sys/capability.h> #include <sys/prctl.h> #include <sys/ptrace.h> #include <sys/types.h> #include <unistd.h> #include <chrono> #include <regex> Loading Loading @@ -569,6 +570,40 @@ TEST_F(CrasherTest, fake_pid) { ASSERT_BACKTRACE_FRAME(result, "tgkill"); } TEST_F(CrasherTest, competing_tracer) { int intercept_result; unique_fd output_fd; StartProcess([]() { while (true) { } }); StartIntercept(&output_fd); FinishCrasher(); ASSERT_EQ(0, ptrace(PTRACE_SEIZE, crasher_pid, 0, 0)); ASSERT_EQ(0, kill(crasher_pid, SIGABRT)); int status; ASSERT_EQ(crasher_pid, waitpid(crasher_pid, &status, 0)); ASSERT_TRUE(WIFSTOPPED(status)); ASSERT_EQ(SIGABRT, WSTOPSIG(status)); ASSERT_EQ(0, ptrace(PTRACE_CONT, crasher_pid, 0, SIGABRT)); FinishIntercept(&intercept_result); ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; std::string result; ConsumeFd(std::move(output_fd), &result); std::string regex = R"(failed to attach to thread \d+, already traced by )"; regex += std::to_string(gettid()); regex += R"( \(.+debuggerd_test)"; ASSERT_MATCH(result, regex.c_str()); ASSERT_EQ(0, ptrace(PTRACE_DETACH, crasher_pid, 0, SIGABRT)); AssertDeath(SIGABRT); } TEST(crash_dump, zombie) { pid_t forkpid = fork(); Loading Loading
debuggerd/crash_dump.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -79,9 +79,27 @@ static bool pid_contains_tid(int pid_proc_fd, pid_t tid) { return fstatat(pid_proc_fd, task_path.c_str(), &st, 0) == 0; } static pid_t get_tracer(pid_t tracee) { // Check to see if the thread is being ptraced by another process. android::procinfo::ProcessInfo process_info; if (android::procinfo::GetProcessInfo(tracee, &process_info)) { return process_info.tracer; } return -1; } // Attach to a thread, and verify that it's still a member of the given process static bool ptrace_seize_thread(int pid_proc_fd, pid_t tid, std::string* error) { if (ptrace(PTRACE_SEIZE, tid, 0, 0) != 0) { if (errno == EPERM) { pid_t tracer = get_tracer(tid); if (tracer != -1) { *error = StringPrintf("failed to attach to thread %d, already traced by %d (%s)", tid, tracer, get_process_name(tracer).c_str()); return false; } } *error = StringPrintf("failed to attach to thread %d: %s", tid, strerror(errno)); return false; } Loading
debuggerd/debuggerd_test.cpp +36 −1 Original line number Diff line number Diff line Loading @@ -16,10 +16,11 @@ #include <err.h> #include <fcntl.h> #include <unistd.h> #include <sys/capability.h> #include <sys/prctl.h> #include <sys/ptrace.h> #include <sys/types.h> #include <unistd.h> #include <chrono> #include <regex> Loading Loading @@ -569,6 +570,40 @@ TEST_F(CrasherTest, fake_pid) { ASSERT_BACKTRACE_FRAME(result, "tgkill"); } TEST_F(CrasherTest, competing_tracer) { int intercept_result; unique_fd output_fd; StartProcess([]() { while (true) { } }); StartIntercept(&output_fd); FinishCrasher(); ASSERT_EQ(0, ptrace(PTRACE_SEIZE, crasher_pid, 0, 0)); ASSERT_EQ(0, kill(crasher_pid, SIGABRT)); int status; ASSERT_EQ(crasher_pid, waitpid(crasher_pid, &status, 0)); ASSERT_TRUE(WIFSTOPPED(status)); ASSERT_EQ(SIGABRT, WSTOPSIG(status)); ASSERT_EQ(0, ptrace(PTRACE_CONT, crasher_pid, 0, SIGABRT)); FinishIntercept(&intercept_result); ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; std::string result; ConsumeFd(std::move(output_fd), &result); std::string regex = R"(failed to attach to thread \d+, already traced by )"; regex += std::to_string(gettid()); regex += R"( \(.+debuggerd_test)"; ASSERT_MATCH(result, regex.c_str()); ASSERT_EQ(0, ptrace(PTRACE_DETACH, crasher_pid, 0, SIGABRT)); AssertDeath(SIGABRT); } TEST(crash_dump, zombie) { pid_t forkpid = fork(); Loading