diff options
author | Josh Gao <jmgao@google.com> | 2017-02-06 18:37:54 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-02-06 18:37:55 +0000 |
commit | 279cb8b39aeda9e8642a52794e6e67aa84fa2af7 (patch) | |
tree | fae2f15b0b9f3ded29a22f2ba52718b5f3285c9e /debuggerd/crash_dump.cpp | |
parent | 564aeca94e18cd708f93619551e05b3d59d4abe2 (diff) | |
parent | b3ee52e4d0ee6f52c78d5f12cdc551686b1ebba7 (diff) |
Merge changes from topic 'debuggerd_ambient'
* changes:
debuggerd_handler: don't use clone(..., SIGCHLD, ...)
crash_dump: drop capabilities after we ptrace attach.
crash_dump: use /proc/<pid> fd to check tid process membership.
debuggerd_handler: raise ambient capset before execing.
Revert "Give crash_dump CAP_SYS_PTRACE."
Diffstat (limited to 'debuggerd/crash_dump.cpp')
-rw-r--r-- | debuggerd/crash_dump.cpp | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp index 58eaed717..ed6d3b7c0 100644 --- a/debuggerd/crash_dump.cpp +++ b/debuggerd/crash_dump.cpp @@ -18,10 +18,12 @@ #include <dirent.h> #include <fcntl.h> #include <stdlib.h> -#include <syscall.h> +#include <sys/capability.h> +#include <sys/prctl.h> #include <sys/ptrace.h> #include <sys/types.h> #include <sys/un.h> +#include <syscall.h> #include <unistd.h> #include <limits> @@ -51,24 +53,25 @@ using android::base::unique_fd; using android::base::StringPrintf; -static bool pid_contains_tid(pid_t pid, pid_t tid) { - std::string task_path = StringPrintf("/proc/%d/task/%d", pid, tid); - return access(task_path.c_str(), F_OK) == 0; +static bool pid_contains_tid(int pid_proc_fd, pid_t tid) { + struct stat st; + std::string task_path = StringPrintf("task/%d", tid); + return fstatat(pid_proc_fd, task_path.c_str(), &st, 0) == 0; } // Attach to a thread, and verify that it's still a member of the given process -static bool ptrace_seize_thread(pid_t pid, 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) { *error = StringPrintf("failed to attach to thread %d: %s", tid, strerror(errno)); return false; } // Make sure that the task we attached to is actually part of the pid we're dumping. - if (!pid_contains_tid(pid, tid)) { + if (!pid_contains_tid(pid_proc_fd, tid)) { if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) { PLOG(FATAL) << "failed to detach from thread " << tid; } - *error = StringPrintf("thread %d is not in process %d", tid, pid); + *error = StringPrintf("thread %d is not in process", tid); return false; } @@ -190,6 +193,24 @@ static void abort_handler(pid_t target, const bool& tombstoned_connected, _exit(1); } +static void drop_capabilities() { + __user_cap_header_struct capheader; + memset(&capheader, 0, sizeof(capheader)); + capheader.version = _LINUX_CAPABILITY_VERSION_3; + capheader.pid = 0; + + __user_cap_data_struct capdata[2]; + memset(&capdata, 0, sizeof(capdata)); + + if (capset(&capheader, &capdata[0]) == -1) { + PLOG(FATAL) << "failed to drop capabilities"; + } + + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) { + PLOG(FATAL) << "failed to set PR_SET_NO_NEW_PRIVS"; + } +} + static void check_process(int proc_fd, pid_t expected_pid) { android::procinfo::ProcessInfo proc_info; if (!android::procinfo::GetProcessInfoFromProcPidFd(proc_fd, &proc_info)) { @@ -263,7 +284,7 @@ int main(int argc, char** argv) { check_process(target_proc_fd, target); std::string attach_error; - if (!ptrace_seize_thread(target, main_tid, &attach_error)) { + if (!ptrace_seize_thread(target_proc_fd, main_tid, &attach_error)) { LOG(FATAL) << attach_error; } @@ -304,6 +325,7 @@ int main(int argc, char** argv) { } int signo = siginfo.si_signo; + bool fatal_signal = signo != DEBUGGER_SIGNAL; bool backtrace = false; uintptr_t abort_address = 0; @@ -319,17 +341,16 @@ int main(int argc, char** argv) { // Now that we have the signal that kicked things off, attach all of the // sibling threads, and then proceed. - bool fatal_signal = signo != DEBUGGER_SIGNAL; - std::set<pid_t> siblings; std::set<pid_t> attached_siblings; - if (fatal_signal || backtrace) { + { + 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, sibling_tid, &attach_error)) { + if (!ptrace_seize_thread(target_proc_fd, sibling_tid, &attach_error)) { LOG(WARNING) << attach_error; } else { attached_siblings.insert(sibling_tid); @@ -337,6 +358,9 @@ int main(int argc, char** argv) { } } + // 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. |