Loading debuggerd/debuggerd.cpp +23 −8 Original line number Diff line number Diff line Loading @@ -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<debugger_request_t*>(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<void*>(request)) == 0); out: freecon(scon); Loading Loading @@ -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. Loading Loading @@ -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(); Loading init/init.cpp +10 −1 Original line number Diff line number Diff line Loading @@ -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<property_audit_data*>(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; } Loading init/property_service.cpp +12 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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<void*>(&audit_data)) == 0) result = 1; freecon(tctx); Loading @@ -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.<service name> Loading @@ -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) { Loading Loading @@ -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", Loading init/property_service.h +6 −0 Original line number Diff line number Diff line Loading @@ -18,9 +18,15 @@ #define _INIT_PROPERTY_H #include <stddef.h> #include <sys/socket.h> #include <sys/system_properties.h> #include <string> 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); Loading Loading
debuggerd/debuggerd.cpp +23 −8 Original line number Diff line number Diff line Loading @@ -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<debugger_request_t*>(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<void*>(request)) == 0); out: freecon(scon); Loading Loading @@ -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. Loading Loading @@ -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(); Loading
init/init.cpp +10 −1 Original line number Diff line number Diff line Loading @@ -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<property_audit_data*>(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; } Loading
init/property_service.cpp +12 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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<void*>(&audit_data)) == 0) result = 1; freecon(tctx); Loading @@ -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.<service name> Loading @@ -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) { Loading Loading @@ -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", Loading
init/property_service.h +6 −0 Original line number Diff line number Diff line Loading @@ -18,9 +18,15 @@ #define _INIT_PROPERTY_H #include <stddef.h> #include <sys/socket.h> #include <sys/system_properties.h> #include <string> 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); Loading