Merge "debuggerd_handler: set PR_SET_DUMPABLE before running crash_dump."
am: af776fd518
Change-Id: I65a4cf9167f1d2804bd5193f492126e74188b43c
This commit is contained in:
commit
877becaf7e
|
@ -238,11 +238,12 @@ int main(int argc, char** argv) {
|
|||
action.sa_handler = signal_handler;
|
||||
debuggerd_register_handlers(&action);
|
||||
|
||||
if (argc != 2) {
|
||||
if (argc != 3) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
pid_t main_tid;
|
||||
pid_t pseudothread_tid;
|
||||
|
||||
if (target == 1) {
|
||||
LOG(FATAL) << "target died before we could attach";
|
||||
|
@ -252,6 +253,10 @@ int main(int argc, char** argv) {
|
|||
LOG(FATAL) << "invalid main tid: " << argv[1];
|
||||
}
|
||||
|
||||
if (!android::base::ParseInt(argv[2], &pseudothread_tid, 1, std::numeric_limits<pid_t>::max())) {
|
||||
LOG(FATAL) << "invalid pseudothread tid: " << argv[1];
|
||||
}
|
||||
|
||||
android::procinfo::ProcessInfo target_info;
|
||||
if (!android::procinfo::GetProcessInfo(main_tid, &target_info)) {
|
||||
LOG(FATAL) << "failed to fetch process info for target " << main_tid;
|
||||
|
@ -284,16 +289,53 @@ int main(int argc, char** argv) {
|
|||
check_process(target_proc_fd, target);
|
||||
|
||||
std::string attach_error;
|
||||
|
||||
// Seize the main thread.
|
||||
if (!ptrace_seize_thread(target_proc_fd, main_tid, &attach_error)) {
|
||||
LOG(FATAL) << attach_error;
|
||||
}
|
||||
|
||||
// Seize the siblings.
|
||||
std::set<pid_t> attached_siblings;
|
||||
{
|
||||
std::set<pid_t> siblings;
|
||||
if (!android::procinfo::GetProcessTids(target, &siblings)) {
|
||||
PLOG(FATAL) << "failed to get process siblings";
|
||||
}
|
||||
|
||||
// but not the already attached main thread.
|
||||
siblings.erase(main_tid);
|
||||
// or the handler pseudothread.
|
||||
siblings.erase(pseudothread_tid);
|
||||
|
||||
for (pid_t sibling_tid : siblings) {
|
||||
if (!ptrace_seize_thread(target_proc_fd, sibling_tid, &attach_error)) {
|
||||
LOG(WARNING) << attach_error;
|
||||
} else {
|
||||
attached_siblings.insert(sibling_tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Collect the backtrace map and open files, while the process still has PR_GET_DUMPABLE=1
|
||||
std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(main_tid));
|
||||
if (!backtrace_map) {
|
||||
LOG(FATAL) << "failed to create backtrace map";
|
||||
}
|
||||
|
||||
// Collect the list of open files.
|
||||
OpenFilesList open_files;
|
||||
populate_open_files_list(target, &open_files);
|
||||
|
||||
// Drop our capabilities now that we've attached to the threads we care about.
|
||||
drop_capabilities();
|
||||
check_process(target_proc_fd, target);
|
||||
|
||||
LOG(INFO) << "obtaining output fd from tombstoned";
|
||||
tombstoned_connected = tombstoned_connect(target, &tombstoned_socket, &output_fd);
|
||||
|
||||
// Write a '\1' to stdout to tell the crashing process to resume.
|
||||
// It also restores the value of PR_SET_DUMPABLE at this point.
|
||||
if (TEMP_FAILURE_RETRY(write(STDOUT_FILENO, "\1", 1)) == -1) {
|
||||
PLOG(ERROR) << "failed to communicate to target process";
|
||||
}
|
||||
|
@ -339,45 +381,9 @@ int main(int argc, char** argv) {
|
|||
abort_address = reinterpret_cast<uintptr_t>(siginfo.si_value.sival_ptr);
|
||||
}
|
||||
|
||||
// Now that we have the signal that kicked things off, attach all of the
|
||||
// sibling threads, and then proceed.
|
||||
std::set<pid_t> attached_siblings;
|
||||
{
|
||||
std::set<pid_t> siblings;
|
||||
if (!android::procinfo::GetProcessTids(target, &siblings)) {
|
||||
PLOG(FATAL) << "failed to get process siblings";
|
||||
}
|
||||
siblings.erase(main_tid);
|
||||
|
||||
for (pid_t sibling_tid : siblings) {
|
||||
if (!ptrace_seize_thread(target_proc_fd, sibling_tid, &attach_error)) {
|
||||
LOG(WARNING) << attach_error;
|
||||
} else {
|
||||
attached_siblings.insert(sibling_tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(main_tid));
|
||||
if (!backtrace_map) {
|
||||
LOG(FATAL) << "failed to create backtrace map";
|
||||
}
|
||||
|
||||
// Collect the list of open files.
|
||||
OpenFilesList open_files;
|
||||
if (!backtrace) {
|
||||
populate_open_files_list(target, &open_files);
|
||||
}
|
||||
|
||||
// Drop our capabilities now that we've attached to the threads we care about.
|
||||
drop_capabilities();
|
||||
|
||||
check_process(target_proc_fd, target);
|
||||
|
||||
// TODO: Use seccomp to lock ourselves down.
|
||||
|
||||
std::string amfd_data;
|
||||
|
||||
if (backtrace) {
|
||||
dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, attached_siblings, 0);
|
||||
} else {
|
||||
|
|
|
@ -254,9 +254,11 @@ static int debuggerd_dispatch_pseudothread(void* arg) {
|
|||
|
||||
raise_caps();
|
||||
|
||||
char buf[10];
|
||||
snprintf(buf, sizeof(buf), "%d", thread_info->crashing_tid);
|
||||
execl(CRASH_DUMP_PATH, CRASH_DUMP_NAME, buf, nullptr);
|
||||
char main_tid[10];
|
||||
char pseudothread_tid[10];
|
||||
snprintf(main_tid, sizeof(main_tid), "%d", thread_info->crashing_tid);
|
||||
snprintf(pseudothread_tid, sizeof(pseudothread_tid), "%d", thread_info->pseudothread_tid);
|
||||
execl(CRASH_DUMP_PATH, CRASH_DUMP_NAME, main_tid, pseudothread_tid, nullptr);
|
||||
|
||||
fatal_errno("exec failed");
|
||||
} else {
|
||||
|
@ -381,6 +383,12 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*)
|
|||
.info = info
|
||||
};
|
||||
|
||||
// Set PR_SET_DUMPABLE to 1, so that crash_dump can ptrace us.
|
||||
int orig_dumpable = prctl(PR_GET_DUMPABLE);
|
||||
if (prctl(PR_SET_DUMPABLE, 1) != 0) {
|
||||
fatal_errno("failed to set dumpable");
|
||||
}
|
||||
|
||||
// Essentially pthread_create without CLONE_FILES (see debuggerd_dispatch_pseudothread).
|
||||
pid_t child_pid =
|
||||
clone(debuggerd_dispatch_pseudothread, pseudothread_stack,
|
||||
|
@ -396,6 +404,11 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*)
|
|||
// and then wait for it to finish.
|
||||
__futex_wait(&thread_info.pseudothread_tid, child_pid, nullptr);
|
||||
|
||||
// Restore PR_SET_DUMPABLE to its original value.
|
||||
if (prctl(PR_SET_DUMPABLE, orig_dumpable) != 0) {
|
||||
fatal_errno("failed to restore dumpable");
|
||||
}
|
||||
|
||||
// Signals can either be fatal or nonfatal.
|
||||
// For fatal signals, crash_dump will PTRACE_CONT us with the signal we
|
||||
// crashed with, so that processes using waitpid on us will see that we
|
||||
|
|
Loading…
Reference in New Issue