diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp index 606456806..258bd761b 100644 --- a/debuggerd/debuggerd.cpp +++ b/debuggerd/debuggerd.cpp @@ -25,9 +25,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -248,6 +250,43 @@ static int read_request(int fd, debugger_request_t* out_request) { return 0; } +static int activity_manager_connect() { + android::base::unique_fd amfd(socket(PF_UNIX, SOCK_STREAM, 0)); + if (amfd.get() < -1) { + ALOGE("debuggerd: Unable to connect to activity manager (socket failed: %s)", strerror(errno)); + return -1; + } + + struct sockaddr_un address; + memset(&address, 0, sizeof(address)); + address.sun_family = AF_UNIX; + // The path used here must match the value defined in NativeCrashListener.java. + strncpy(address.sun_path, "/data/system/ndebugsocket", sizeof(address.sun_path)); + if (TEMP_FAILURE_RETRY(connect(amfd.get(), reinterpret_cast(&address), + sizeof(address))) == -1) { + ALOGE("debuggerd: Unable to connect to activity manager (connect failed: %s)", strerror(errno)); + return -1; + } + + struct timeval tv; + memset(&tv, 0, sizeof(tv)); + tv.tv_sec = 1; // tight leash + if (setsockopt(amfd.get(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) { + ALOGE("debuggerd: Unable to connect to activity manager (setsockopt SO_SNDTIMEO failed: %s)", + strerror(errno)); + return -1; + } + + tv.tv_sec = 3; // 3 seconds on handshake read + if (setsockopt(amfd.get(), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) { + ALOGE("debuggerd: Unable to connect to activity manager (setsockopt SO_RCVTIMEO failed: %s)", + strerror(errno)); + return -1; + } + + return amfd.release(); +} + static bool should_attach_gdb(const debugger_request_t& request) { if (request.action == DEBUGGER_ACTION_CRASH) { return property_get_bool("debug.debuggerd.wait_for_gdb", false); @@ -375,7 +414,7 @@ static void ptrace_siblings(pid_t pid, pid_t main_tid, std::set& tids) { static bool perform_dump(const debugger_request_t& request, int fd, int tombstone_fd, BacktraceMap* backtrace_map, const std::set& siblings, - int* crash_signal) { + int* crash_signal, int amfd) { if (TEMP_FAILURE_RETRY(write(fd, "\0", 1)) != 1) { ALOGE("debuggerd: failed to respond to client: %s\n", strerror(errno)); return false; @@ -393,7 +432,7 @@ static bool perform_dump(const debugger_request_t& request, int fd, int tombston if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) { ALOGV("debuggerd: stopped -- dumping to tombstone"); engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal, - request.original_si_code, request.abort_msg_address); + request.original_si_code, request.abort_msg_address, amfd); } else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) { ALOGV("debuggerd: stopped -- dumping to fd"); dump_backtrace(fd, -1, backtrace_map, request.pid, request.tid, siblings); @@ -419,7 +458,7 @@ static bool perform_dump(const debugger_request_t& request, int fd, int tombston ALOGV("stopped -- fatal signal\n"); *crash_signal = signal; engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal, - request.original_si_code, request.abort_msg_address); + request.original_si_code, request.abort_msg_address, amfd); break; default: @@ -505,6 +544,12 @@ static void worker_process(int fd, debugger_request_t& request) { // Generate the backtrace map before dropping privileges. std::unique_ptr backtrace_map(BacktraceMap::Create(request.pid)); + int amfd = -1; + if (request.action == DEBUGGER_ACTION_CRASH) { + // Connect to the activity manager before dropping privileges. + amfd = activity_manager_connect(); + } + bool succeeded = false; // Now that we've done everything that requires privileges, we can drop them. @@ -514,7 +559,8 @@ static void worker_process(int fd, debugger_request_t& request) { } int crash_signal = SIGKILL; - succeeded = perform_dump(request, fd, tombstone_fd, backtrace_map.get(), siblings, &crash_signal); + succeeded = perform_dump(request, fd, tombstone_fd, backtrace_map.get(), siblings, + &crash_signal, amfd); if (succeeded) { if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) { if (!tombstone_path.empty()) { @@ -558,6 +604,8 @@ static void worker_process(int fd, debugger_request_t& request) { uninit_getevent(); } + close(amfd); + exit(!succeeded); } diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp index 7cf2ffc71..d802c8c07 100644 --- a/debuggerd/tombstone.cpp +++ b/debuggerd/tombstone.cpp @@ -28,9 +28,7 @@ #include #include #include -#include #include -#include #include #include @@ -59,9 +57,6 @@ #define TOMBSTONE_DIR "/data/tombstones" #define TOMBSTONE_TEMPLATE (TOMBSTONE_DIR"/tombstone_%02d") -// Must match the path defined in NativeCrashListener.java -#define NCRASH_SOCKET_PATH "/data/system/ndebugsocket" - static bool signal_has_si_addr(int sig) { switch (sig) { case SIGBUS: @@ -711,39 +706,9 @@ int open_tombstone(std::string* out_path) { return fd; } -static int activity_manager_connect() { - int amfd = socket(PF_UNIX, SOCK_STREAM, 0); - if (amfd >= 0) { - struct sockaddr_un address; - int err; - - memset(&address, 0, sizeof(address)); - address.sun_family = AF_UNIX; - strncpy(address.sun_path, NCRASH_SOCKET_PATH, sizeof(address.sun_path)); - err = TEMP_FAILURE_RETRY(connect( - amfd, reinterpret_cast(&address), sizeof(address))); - if (!err) { - struct timeval tv; - memset(&tv, 0, sizeof(tv)); - tv.tv_sec = 1; // tight leash - err = setsockopt(amfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); - if (!err) { - tv.tv_sec = 3; // 3 seconds on handshake read - err = setsockopt(amfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); - } - } - if (err) { - close(amfd); - amfd = -1; - } - } - - return amfd; -} - void engrave_tombstone(int tombstone_fd, BacktraceMap* map, pid_t pid, pid_t tid, const std::set& siblings, int signal, int original_si_code, - uintptr_t abort_msg_address) { + uintptr_t abort_msg_address, int amfd) { log_t log; log.current_tid = tid; log.crashed_tid = tid; @@ -756,10 +721,6 @@ void engrave_tombstone(int tombstone_fd, BacktraceMap* map, pid_t pid, pid_t tid log.tfd = tombstone_fd; // Preserve amfd since it can be modified through the calls below without // being closed. - int amfd = activity_manager_connect(); log.amfd = amfd; dump_crash(&log, map, pid, tid, siblings, signal, original_si_code, abort_msg_address); - - // This file descriptor can be -1, any error is ignored. - close(amfd); } diff --git a/debuggerd/tombstone.h b/debuggerd/tombstone.h index 2b8b8bed7..7f3eebe0b 100644 --- a/debuggerd/tombstone.h +++ b/debuggerd/tombstone.h @@ -34,6 +34,6 @@ int open_tombstone(std::string* path); /* Creates a tombstone file and writes the crash dump to it. */ void engrave_tombstone(int tombstone_fd, BacktraceMap* map, pid_t pid, pid_t tid, const std::set& siblings, int signal, int original_si_code, - uintptr_t abort_msg_address); + uintptr_t abort_msg_address, int amfd); #endif // _DEBUGGERD_TOMBSTONE_H