diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp index 599995cfd..713638d11 100644 --- a/debuggerd/debuggerd.cpp +++ b/debuggerd/debuggerd.cpp @@ -130,31 +130,44 @@ static const char *debuggerd_perms[] = { "dump_backtrace" }; -static bool selinux_action_allowed(int s, pid_t tid, debugger_action_t action) +static int audit_callback(void* data, security_class_t /* cls */, char* buf, size_t len) +{ + struct debugger_request_t* req = reinterpret_cast(data); + + if (!req) { + ALOGE("No debuggerd request audit data"); + return 0; + } + + snprintf(buf, len, "pid=%d uid=%d gid=%d", req->pid, req->uid, req->gid); + return 0; +} + +static bool selinux_action_allowed(int s, debugger_request_t* request) { char *scon = NULL, *tcon = NULL; const char *tclass = "debuggerd"; const char *perm; bool allowed = false; - if (action <= 0 || action >= (sizeof(debuggerd_perms)/sizeof(debuggerd_perms[0]))) { - ALOGE("SELinux: No permission defined for debugger action %d", action); + if (request->action <= 0 || request->action >= (sizeof(debuggerd_perms)/sizeof(debuggerd_perms[0]))) { + ALOGE("SELinux: No permission defined for debugger action %d", request->action); return false; } - perm = debuggerd_perms[action]; + perm = debuggerd_perms[request->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); + if (getpidcon(request->tid, &tcon) < 0) { + ALOGE("Cannot get context for tid %d\n", request->tid); goto out; } - allowed = (selinux_check_access(scon, tcon, tclass, perm, NULL) == 0); + allowed = (selinux_check_access(scon, tcon, tclass, perm, reinterpret_cast(request)) == 0); out: freecon(scon); @@ -225,7 +238,7 @@ static int read_request(int fd, debugger_request_t* out_request) { return -1; } - if (!selinux_action_allowed(fd, out_request->tid, out_request->action)) + if (!selinux_action_allowed(fd, out_request)) return -1; } else { // No one else is allowed to dump arbitrary processes. @@ -566,6 +579,8 @@ static void usage() { int main(int argc, char** argv) { union selinux_callback cb; if (argc == 1) { + cb.func_audit = audit_callback; + selinux_set_callback(SELINUX_CB_AUDIT, cb); cb.func_log = selinux_log_callback; selinux_set_callback(SELINUX_CB_LOG, cb); return do_server(); diff --git a/init/init.cpp b/init/init.cpp index ee1351d95..a898b03e3 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -467,7 +467,16 @@ int selinux_reload_policy(void) } static int audit_callback(void *data, security_class_t /*cls*/, char *buf, size_t len) { - snprintf(buf, len, "property=%s", !data ? "NULL" : (char *)data); + + property_audit_data *d = reinterpret_cast(data); + + if (!d || !d->name || !d->cr) { + ERROR("audit_callback invoked with null data arguments!"); + return 0; + } + + snprintf(buf, len, "property=%s pid=%d uid=%d gid=%d", d->name, + d->cr->pid, d->cr->uid, d->cr->gid); return 0; } diff --git a/init/property_service.cpp b/init/property_service.cpp index a37d6f661..96b4a37b2 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp @@ -90,10 +90,11 @@ void property_init() { } } -static int check_mac_perms(const char *name, char *sctx) +static int check_mac_perms(const char *name, char *sctx, struct ucred *cr) { char *tctx = NULL; int result = 0; + property_audit_data audit_data; if (!sctx) goto err; @@ -104,7 +105,10 @@ static int check_mac_perms(const char *name, char *sctx) if (selabel_lookup(sehandle_prop, &tctx, name, 1) != 0) goto err; - if (selinux_check_access(sctx, tctx, "property_service", "set", (void*) name) == 0) + audit_data.name = name; + audit_data.cr = cr; + + if (selinux_check_access(sctx, tctx, "property_service", "set", reinterpret_cast(&audit_data)) == 0) result = 1; freecon(tctx); @@ -112,7 +116,7 @@ static int check_mac_perms(const char *name, char *sctx) return result; } -static int check_control_mac_perms(const char *name, char *sctx) +static int check_control_mac_perms(const char *name, char *sctx, struct ucred *cr) { /* * Create a name prefix out of ctl. @@ -126,19 +130,19 @@ static int check_control_mac_perms(const char *name, char *sctx) if (ret < 0 || (size_t) ret >= sizeof(ctl_name)) return 0; - return check_mac_perms(ctl_name, sctx); + return check_mac_perms(ctl_name, sctx, cr); } /* * Checks permissions for setting system properties. * Returns 1 if uid allowed, 0 otherwise. */ -static int check_perms(const char *name, char *sctx) +static int check_perms(const char *name, char *sctx, struct ucred *cr) { if(!strncmp(name, "ro.", 3)) name +=3; - return check_mac_perms(name, sctx); + return check_mac_perms(name, sctx, cr); } std::string property_get(const char* name) { @@ -321,14 +325,14 @@ static void handle_property_set_fd() // Keep the old close-socket-early behavior when handling // ctl.* properties. close(s); - if (check_control_mac_perms(msg.value, source_ctx)) { + if (check_control_mac_perms(msg.value, source_ctx, &cr)) { handle_control_message((char*) msg.name + 4, (char*) msg.value); } else { ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n", msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid); } } else { - if (check_perms(msg.name, source_ctx)) { + if (check_perms(msg.name, source_ctx, &cr)) { property_set((char*) msg.name, (char*) msg.value); } else { ERROR("sys_prop: permission denied uid:%d name:%s\n", diff --git a/init/property_service.h b/init/property_service.h index f30577b47..8b76d2b3f 100644 --- a/init/property_service.h +++ b/init/property_service.h @@ -18,9 +18,15 @@ #define _INIT_PROPERTY_H #include +#include #include #include +struct property_audit_data { + ucred *cr; + const char* name; +}; + extern void property_init(void); extern void property_load_boot_defaults(void); extern void load_persist_props(void);