am 2fb90dc8: Merge changes from topic \'userspace-audit\'
* commit '2fb90dc8b2b590e674c5e433e8bf3d3f08a887c8': debuggerd: audit pid, uid and gid on SE Linux denial property_service: log pid,uid and gid of setprop client
This commit is contained in:
commit
545b7c9e39
|
@ -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);
|
||||
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<void*>(&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.<service name>
|
||||
|
@ -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",
|
||||
|
|
|
@ -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…
Reference in New Issue