diff options
author | William Roberts <william.c.roberts@intel.com> | 2015-10-01 22:02:15 -0700 |
---|---|---|
committer | William Roberts <william.c.roberts@intel.com> | 2015-10-05 11:38:20 -0700 |
commit | 8fb0f92e0fe3c286ebb120bae9e1570ee109fa12 (patch) | |
tree | 9776e15194df3193779b96e27e218b80fc2ef350 | |
parent | bd55551d80832f62931ccb2d54d9a239822eeb20 (diff) | |
download | native-8fb0f92e0fe3c286ebb120bae9e1570ee109fa12.tar.gz |
servicemanager: log pid and uid on selinux denial
The audit logs for servicemanager were missing the pid and uid of the source.
This is useful for debugging.
Before:
... SELinux : avc: denied { find } for service=android.security.keystore scontext=u:r:system_app:s0 ...
After:
... SELinux : avc: denied { find } for service=android.security.keystore pid=1252 uid=1000 scontext=u:r:system_app:s0 ...
Change-Id: Id1a6f38b99f11a31315439620ead2f01108b18b2
Signed-off-by: William Roberts <william.c.roberts@intel.com>
-rw-r--r-- | cmds/servicemanager/service_manager.c | 50 |
1 files changed, 34 insertions, 16 deletions
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c index 7fa9a39f79..8596f962bd 100644 --- a/cmds/servicemanager/service_manager.c +++ b/cmds/servicemanager/service_manager.c @@ -23,6 +23,12 @@ #include <cutils/log.h> #endif +struct audit_data { + pid_t pid; + uid_t uid; + const char *name; +}; + const char *str8(const uint16_t *x, size_t x_len) { static char buf[128]; @@ -56,34 +62,39 @@ static int selinux_enabled; static char *service_manager_context; static struct selabel_handle* sehandle; -static bool check_mac_perms(pid_t spid, const char *tctx, const char *perm, const char *name) +static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name) { char *sctx = NULL; const char *class = "service_manager"; bool allowed; + struct audit_data ad; if (getpidcon(spid, &sctx) < 0) { ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid); return false; } - int result = selinux_check_access(sctx, tctx, class, perm, (void *) name); + ad.pid = spid; + ad.uid = uid; + ad.name = name; + + int result = selinux_check_access(sctx, tctx, class, perm, (void *) &ad); allowed = (result == 0); freecon(sctx); return allowed; } -static bool check_mac_perms_from_getcon(pid_t spid, const char *perm) +static bool check_mac_perms_from_getcon(pid_t spid, uid_t uid, const char *perm) { if (selinux_enabled <= 0) { return true; } - return check_mac_perms(spid, service_manager_context, perm, NULL); + return check_mac_perms(spid, uid, service_manager_context, perm, NULL); } -static bool check_mac_perms_from_lookup(pid_t spid, const char *perm, const char *name) +static bool check_mac_perms_from_lookup(pid_t spid, uid_t uid, const char *perm, const char *name) { bool allowed; char *tctx = NULL; @@ -102,27 +113,27 @@ static bool check_mac_perms_from_lookup(pid_t spid, const char *perm, const char return false; } - allowed = check_mac_perms(spid, tctx, perm, name); + allowed = check_mac_perms(spid, uid, tctx, perm, name); freecon(tctx); return allowed; } -static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid) +static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid) { const char *perm = "add"; - return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0; + return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0; } -static int svc_can_list(pid_t spid) +static int svc_can_list(pid_t spid, uid_t uid) { const char *perm = "list"; - return check_mac_perms_from_getcon(spid, perm) ? 1 : 0; + return check_mac_perms_from_getcon(spid, uid, perm) ? 1 : 0; } -static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid) +static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid) { const char *perm = "find"; - return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0; + return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0; } struct svcinfo @@ -184,7 +195,7 @@ uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, } } - if (!svc_can_find(s, len, spid)) { + if (!svc_can_find(s, len, spid, uid)) { return 0; } @@ -204,7 +215,7 @@ int do_add_service(struct binder_state *bs, if (!handle || (len == 0) || (len > 127)) return -1; - if (!svc_can_register(s, len, spid)) { + if (!svc_can_register(s, len, spid, uid)) { ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n", str8(s, len), handle, uid); return -1; @@ -314,7 +325,7 @@ int svcmgr_handler(struct binder_state *bs, case SVC_MGR_LIST_SERVICES: { uint32_t n = bio_get_uint32(msg); - if (!svc_can_list(txn->sender_pid)) { + if (!svc_can_list(txn->sender_pid, txn->sender_euid)) { ALOGE("list_service() uid=%d - PERMISSION DENIED\n", txn->sender_euid); return -1; @@ -340,7 +351,14 @@ int svcmgr_handler(struct binder_state *bs, static int audit_callback(void *data, security_class_t cls, char *buf, size_t len) { - snprintf(buf, len, "service=%s", !data ? "NULL" : (char *)data); + struct audit_data *ad = (struct audit_data *)data; + + if (!ad || !ad->name) { + ALOGE("No service manager audit data"); + return 0; + } + + snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name, ad->pid, ad->uid); return 0; } |