Add SELinux MAC to debuggerd.
debuggerd allows uid-0 processes to dump tombstones or backtraces of any process, and uid-system processes to dump backtraces of any processes. Restrict these operations via SELinux based on the client context, the target process context, and the action. Depends on I8e120d319512ff207ed22ed87cde4e0432a13dda for the corresponding policy definitions. Change-Id: Ib317564e54e07cc21f259e75124b762ad17c6e16 Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
This commit is contained in:
parent
73290cd136
commit
69b800391c
|
@ -30,6 +30,8 @@
|
|||
#include <sys/stat.h>
|
||||
#include <sys/poll.h>
|
||||
|
||||
#include <selinux/android.h>
|
||||
|
||||
#include <log/logger.h>
|
||||
|
||||
#include <cutils/sockets.h>
|
||||
|
@ -124,6 +126,53 @@ static int get_process_info(pid_t tid, pid_t* out_pid, uid_t* out_uid, uid_t* ou
|
|||
return fields == 7 ? 0 : -1;
|
||||
}
|
||||
|
||||
static int selinux_enabled;
|
||||
|
||||
/*
|
||||
* Corresponds with debugger_action_t enum type in
|
||||
* include/cutils/debugger.h.
|
||||
*/
|
||||
static const char *debuggerd_perms[] = {
|
||||
NULL, /* crash is only used on self, no check applied */
|
||||
"dump_tombstone",
|
||||
"dump_backtrace"
|
||||
};
|
||||
|
||||
static bool selinux_action_allowed(int s, pid_t tid, debugger_action_t action)
|
||||
{
|
||||
char *scon = NULL, *tcon = NULL;
|
||||
const char *tclass = "debuggerd";
|
||||
const char *perm;
|
||||
bool allowed = false;
|
||||
|
||||
if (selinux_enabled <= 0)
|
||||
return true;
|
||||
|
||||
if (action <= 0 || action >= (sizeof(debuggerd_perms)/sizeof(debuggerd_perms[0]))) {
|
||||
ALOGE("SELinux: No permission defined for debugger action %d", action);
|
||||
return false;
|
||||
}
|
||||
|
||||
perm = debuggerd_perms[action];
|
||||
|
||||
if (getpeercon(s, &scon) < 0) {
|
||||
ALOGE("Cannot get peer context from socket\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (getpidcon(tid, &tcon) < 0) {
|
||||
ALOGE("Cannot get context for tid %d\n", tid);
|
||||
goto out;
|
||||
}
|
||||
|
||||
allowed = (selinux_check_access(scon, tcon, tclass, perm, NULL) == 0);
|
||||
|
||||
out:
|
||||
freecon(scon);
|
||||
freecon(tcon);
|
||||
return allowed;
|
||||
}
|
||||
|
||||
static int read_request(int fd, debugger_request_t* out_request) {
|
||||
ucred cr;
|
||||
socklen_t len = sizeof(cr);
|
||||
|
@ -186,6 +235,9 @@ static int read_request(int fd, debugger_request_t* out_request) {
|
|||
ALOGE("tid %d does not exist. ignoring explicit dump request\n", out_request->tid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!selinux_action_allowed(fd, out_request->tid, out_request->action))
|
||||
return -1;
|
||||
} else {
|
||||
// No one else is allowed to dump arbitrary processes.
|
||||
return -1;
|
||||
|
@ -434,7 +486,11 @@ static void usage() {
|
|||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
union selinux_callback cb;
|
||||
if (argc == 1) {
|
||||
selinux_enabled = is_selinux_enabled();
|
||||
cb.func_log = selinux_log_callback;
|
||||
selinux_set_callback(SELINUX_CB_LOG, cb);
|
||||
return do_server();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue