summaryrefslogtreecommitdiffstats
path: root/debuggerd
diff options
context:
space:
mode:
authorJosh Gao <jmgao@google.com>2017-08-18 15:37:26 -0700
committerJosh Gao <jmgao@google.com>2017-08-18 16:16:58 -0700
commitfd13bf0dcd374e98a3acd8e3d3672221aef94c7c (patch)
tree0b26dc2667b938e0c522307d80707b9eae88eb3b /debuggerd
parentde6b44aa0ec047aacf277ce797574b50f406d589 (diff)
downloadsystem_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.cpp18
-rw-r--r--debuggerd/debuggerd_test.cpp37
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();