diff options
author | Josh Gao <jmgao@google.com> | 2017-08-18 15:37:26 -0700 |
---|---|---|
committer | Josh Gao <jmgao@google.com> | 2017-08-18 16:16:58 -0700 |
commit | fd13bf0dcd374e98a3acd8e3d3672221aef94c7c (patch) | |
tree | 0b26dc2667b938e0c522307d80707b9eae88eb3b /debuggerd | |
parent | de6b44aa0ec047aacf277ce797574b50f406d589 (diff) | |
download | system_core-fd13bf0dcd374e98a3acd8e3d3672221aef94c7c.tar.gz system_core-fd13bf0dcd374e98a3acd8e3d3672221aef94c7c.tar.bz2 system_core-fd13bf0dcd374e98a3acd8e3d3672221aef94c7c.zip |
crash_dump: print the identity of tracers.
Instead of printing a useless "ptrace attach failed: strerror(EPERM)"
message, print the name and pid of a competing tracer when we fail to
attach because a process is already being ptraced.
Bug: http://b/31531918
Test: debuggerd_test32, debuggerd_test64 on aosp_angler
Test: strace -p `pidof surfaceflinger`; debuggerd -b surfaceflinger
Change-Id: Ifd3f80fe03de30ff38c0e0068560a7b12875f29d
Diffstat (limited to 'debuggerd')
-rw-r--r-- | debuggerd/crash_dump.cpp | 18 | ||||
-rw-r--r-- | debuggerd/debuggerd_test.cpp | 37 |
2 files changed, 54 insertions, 1 deletions
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp index 4b1e51dde..cd1da50f5 100644 --- a/debuggerd/crash_dump.cpp +++ b/debuggerd/crash_dump.cpp @@ -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; } diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp index b51fc665e..dbf81a4ee 100644 --- a/debuggerd/debuggerd_test.cpp +++ b/debuggerd/debuggerd_test.cpp @@ -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> @@ -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(); |