Loading debuggerd/debuggerd.cpp +52 −4 Original line number Diff line number Diff line Loading @@ -25,9 +25,11 @@ #include <sys/poll.h> #include <sys/prctl.h> #include <sys/ptrace.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/un.h> #include <time.h> #include <set> Loading Loading @@ -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<struct sockaddr*>(&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); Loading Loading @@ -375,7 +414,7 @@ static void ptrace_siblings(pid_t pid, pid_t main_tid, std::set<pid_t>& tids) { static bool perform_dump(const debugger_request_t& request, int fd, int tombstone_fd, BacktraceMap* backtrace_map, const std::set<pid_t>& 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; Loading @@ -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); Loading @@ -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: Loading Loading @@ -505,6 +544,12 @@ static void worker_process(int fd, debugger_request_t& request) { // Generate the backtrace map before dropping privileges. std::unique_ptr<BacktraceMap> 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. Loading @@ -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()) { Loading Loading @@ -558,6 +604,8 @@ static void worker_process(int fd, debugger_request_t& request) { uninit_getevent(); } close(amfd); exit(!succeeded); } Loading debuggerd/tombstone.cpp +1 −40 Original line number Diff line number Diff line Loading @@ -28,9 +28,7 @@ #include <string.h> #include <time.h> #include <sys/ptrace.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/un.h> #include <memory> #include <string> Loading Loading @@ -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: Loading Loading @@ -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<struct sockaddr*>(&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<pid_t>& 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; Loading @@ -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); } debuggerd/tombstone.h +1 −1 Original line number Diff line number Diff line Loading @@ -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<pid_t>& siblings, int signal, int original_si_code, uintptr_t abort_msg_address); uintptr_t abort_msg_address, int amfd); #endif // _DEBUGGERD_TOMBSTONE_H Loading
debuggerd/debuggerd.cpp +52 −4 Original line number Diff line number Diff line Loading @@ -25,9 +25,11 @@ #include <sys/poll.h> #include <sys/prctl.h> #include <sys/ptrace.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/un.h> #include <time.h> #include <set> Loading Loading @@ -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<struct sockaddr*>(&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); Loading Loading @@ -375,7 +414,7 @@ static void ptrace_siblings(pid_t pid, pid_t main_tid, std::set<pid_t>& tids) { static bool perform_dump(const debugger_request_t& request, int fd, int tombstone_fd, BacktraceMap* backtrace_map, const std::set<pid_t>& 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; Loading @@ -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); Loading @@ -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: Loading Loading @@ -505,6 +544,12 @@ static void worker_process(int fd, debugger_request_t& request) { // Generate the backtrace map before dropping privileges. std::unique_ptr<BacktraceMap> 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. Loading @@ -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()) { Loading Loading @@ -558,6 +604,8 @@ static void worker_process(int fd, debugger_request_t& request) { uninit_getevent(); } close(amfd); exit(!succeeded); } Loading
debuggerd/tombstone.cpp +1 −40 Original line number Diff line number Diff line Loading @@ -28,9 +28,7 @@ #include <string.h> #include <time.h> #include <sys/ptrace.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/un.h> #include <memory> #include <string> Loading Loading @@ -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: Loading Loading @@ -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<struct sockaddr*>(&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<pid_t>& 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; Loading @@ -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); }
debuggerd/tombstone.h +1 −1 Original line number Diff line number Diff line Loading @@ -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<pid_t>& siblings, int signal, int original_si_code, uintptr_t abort_msg_address); uintptr_t abort_msg_address, int amfd); #endif // _DEBUGGERD_TOMBSTONE_H