Connect to activity manager as root.
Before dropping root privileges, connect to the activity manager.
Also, only connect to the activity manager if this is a crash.
Bug: 28210681
(cherry picked from commit 0fc89f34b9
)
Change-Id: Id25b92e550d71ffe1b9eafe43976ef514a83714b
This commit is contained in:
parent
0652728e2a
commit
8fb38ae82d
3 changed files with 54 additions and 45 deletions
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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<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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
@ -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<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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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…
Reference in a new issue