Merge "crash_dump: print the identity of tracers."
am: e67c7b94c2
Change-Id: Ic926e668cee9163a3caadcd6313ff4bc76c2768f
This commit is contained in:
commit
68f92308ec
2 changed files with 54 additions and 1 deletions
|
|
@ -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;
|
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
|
// 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) {
|
static bool ptrace_seize_thread(int pid_proc_fd, pid_t tid, std::string* error) {
|
||||||
if (ptrace(PTRACE_SEIZE, tid, 0, 0) != 0) {
|
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));
|
*error = StringPrintf("failed to attach to thread %d: %s", tid, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,11 @@
|
||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/capability.h>
|
#include <sys/capability.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
#include <sys/ptrace.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
@ -569,6 +570,40 @@ TEST_F(CrasherTest, fake_pid) {
|
||||||
ASSERT_BACKTRACE_FRAME(result, "tgkill");
|
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) {
|
TEST(crash_dump, zombie) {
|
||||||
pid_t forkpid = fork();
|
pid_t forkpid = fork();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue