Loading cmds/servicemanager/service_manager.c +75 −35 Original line number Diff line number Diff line Loading @@ -52,60 +52,77 @@ int str16eq(const uint16_t *a, const char *b) return 1; } static int selinux_enabled; static char *service_manager_context; static struct selabel_handle* sehandle; static bool check_mac_perms(const char *name, pid_t spid) static bool check_mac_perms(pid_t spid, const char *tctx, const char *perm, const char *name) { if (is_selinux_enabled() <= 0) { return true; } char *sctx = NULL; const char *class = "service_manager"; bool allowed; bool allowed = false; if (getpidcon(spid, &sctx) < 0) { ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid); return false; } const char *class = "service_manager"; const char *perm = "add"; int result = selinux_check_access(sctx, tctx, class, perm, (void *) name); allowed = (result == 0); char *tctx = NULL; char *sctx = NULL; freecon(sctx); return allowed; } if (!sehandle) { ALOGE("SELinux: Failed to find sehandle %s.\n", name); return false; static bool check_mac_perms_from_getcon(pid_t spid, const char *perm) { if (selinux_enabled <= 0) { return true; } if (getpidcon(spid, &sctx) < 0) { ALOGE("SELinux: getpidcon failed to retrieve pid context.\n"); return false; return check_mac_perms(spid, service_manager_context, perm, NULL); } if (!sctx) { ALOGE("SELinux: Failed to find sctx for %s.\n", name); return false; static bool check_mac_perms_from_lookup(pid_t spid, const char *perm, const char *name) { bool allowed; char *tctx = NULL; if (selinux_enabled <= 0) { return true; } if (selabel_lookup(sehandle, &tctx, name, 1) != 0) { ALOGE("SELinux: selabel_lookup failed to set tctx for %s.\n", name); freecon(sctx); return false; if (!sehandle) { ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n"); abort(); } if (!tctx) { ALOGE("SELinux: Failed to find tctx for %s.\n", name); freecon(sctx); if (selabel_lookup(sehandle, &tctx, name, 0) != 0) { ALOGE("SELinux: No match for %s in service_contexts.\n", name); return false; } int result = selinux_check_access(sctx, tctx, class, perm, (void *) name); allowed = (result == 0); freecon(sctx); allowed = check_mac_perms(spid, tctx, perm, name); freecon(tctx); return allowed; } static int svc_can_register(uid_t uid, 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) { const char *perm = "add"; return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0; } static int svc_can_list(pid_t spid) { return check_mac_perms(str8(name, name_len), spid) ? 1 : 0; const char *perm = "list"; return check_mac_perms_from_getcon(spid, perm) ? 1 : 0; } static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid) { const char *perm = "find"; return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0; } struct svcinfo Loading Loading @@ -150,10 +167,15 @@ uint16_t svcmgr_id[] = { }; uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid) uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid) { struct svcinfo *si; if (!svc_can_find(s, len, spid)) { ALOGE("find_service('%s') uid=%d - PERMISSION DENIED\n", str8(s, len), uid); return 0; } si = find_svc(s, len); //ALOGI("check_service('%s') handle = %x\n", str8(s, len), si ? si->handle : 0); if (si && si->handle) { Loading Loading @@ -184,7 +206,7 @@ int do_add_service(struct binder_state *bs, if (!handle || (len == 0) || (len > 127)) return -1; if (!svc_can_register(uid, s, len, spid)) { if (!svc_can_register(s, len, spid)) { ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n", str8(s, len), handle, uid); return -1; Loading Loading @@ -273,7 +295,7 @@ int svcmgr_handler(struct binder_state *bs, if (s == NULL) { return -1; } handle = do_find_service(bs, s, len, txn->sender_euid); handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid); if (!handle) break; bio_put_ref(reply, handle); Loading @@ -294,6 +316,11 @@ 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)) { ALOGE("list_service() uid=%d - PERMISSION DENIED\n", txn->sender_euid); return -1; } si = svclist; while ((n-- > 0) && si) si = si->next; Loading Loading @@ -334,8 +361,21 @@ int main(int argc, char **argv) return -1; } selinux_enabled = is_selinux_enabled(); sehandle = selinux_android_service_context_handle(); if (selinux_enabled > 0) { if (sehandle == NULL) { ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n"); abort(); } if (getcon(&service_manager_context) != 0) { ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n"); abort(); } } union selinux_callback cb; cb.func_audit = audit_callback; selinux_set_callback(SELINUX_CB_AUDIT, cb); Loading Loading
cmds/servicemanager/service_manager.c +75 −35 Original line number Diff line number Diff line Loading @@ -52,60 +52,77 @@ int str16eq(const uint16_t *a, const char *b) return 1; } static int selinux_enabled; static char *service_manager_context; static struct selabel_handle* sehandle; static bool check_mac_perms(const char *name, pid_t spid) static bool check_mac_perms(pid_t spid, const char *tctx, const char *perm, const char *name) { if (is_selinux_enabled() <= 0) { return true; } char *sctx = NULL; const char *class = "service_manager"; bool allowed; bool allowed = false; if (getpidcon(spid, &sctx) < 0) { ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid); return false; } const char *class = "service_manager"; const char *perm = "add"; int result = selinux_check_access(sctx, tctx, class, perm, (void *) name); allowed = (result == 0); char *tctx = NULL; char *sctx = NULL; freecon(sctx); return allowed; } if (!sehandle) { ALOGE("SELinux: Failed to find sehandle %s.\n", name); return false; static bool check_mac_perms_from_getcon(pid_t spid, const char *perm) { if (selinux_enabled <= 0) { return true; } if (getpidcon(spid, &sctx) < 0) { ALOGE("SELinux: getpidcon failed to retrieve pid context.\n"); return false; return check_mac_perms(spid, service_manager_context, perm, NULL); } if (!sctx) { ALOGE("SELinux: Failed to find sctx for %s.\n", name); return false; static bool check_mac_perms_from_lookup(pid_t spid, const char *perm, const char *name) { bool allowed; char *tctx = NULL; if (selinux_enabled <= 0) { return true; } if (selabel_lookup(sehandle, &tctx, name, 1) != 0) { ALOGE("SELinux: selabel_lookup failed to set tctx for %s.\n", name); freecon(sctx); return false; if (!sehandle) { ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n"); abort(); } if (!tctx) { ALOGE("SELinux: Failed to find tctx for %s.\n", name); freecon(sctx); if (selabel_lookup(sehandle, &tctx, name, 0) != 0) { ALOGE("SELinux: No match for %s in service_contexts.\n", name); return false; } int result = selinux_check_access(sctx, tctx, class, perm, (void *) name); allowed = (result == 0); freecon(sctx); allowed = check_mac_perms(spid, tctx, perm, name); freecon(tctx); return allowed; } static int svc_can_register(uid_t uid, 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) { const char *perm = "add"; return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0; } static int svc_can_list(pid_t spid) { return check_mac_perms(str8(name, name_len), spid) ? 1 : 0; const char *perm = "list"; return check_mac_perms_from_getcon(spid, perm) ? 1 : 0; } static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid) { const char *perm = "find"; return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0; } struct svcinfo Loading Loading @@ -150,10 +167,15 @@ uint16_t svcmgr_id[] = { }; uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid) uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid) { struct svcinfo *si; if (!svc_can_find(s, len, spid)) { ALOGE("find_service('%s') uid=%d - PERMISSION DENIED\n", str8(s, len), uid); return 0; } si = find_svc(s, len); //ALOGI("check_service('%s') handle = %x\n", str8(s, len), si ? si->handle : 0); if (si && si->handle) { Loading Loading @@ -184,7 +206,7 @@ int do_add_service(struct binder_state *bs, if (!handle || (len == 0) || (len > 127)) return -1; if (!svc_can_register(uid, s, len, spid)) { if (!svc_can_register(s, len, spid)) { ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n", str8(s, len), handle, uid); return -1; Loading Loading @@ -273,7 +295,7 @@ int svcmgr_handler(struct binder_state *bs, if (s == NULL) { return -1; } handle = do_find_service(bs, s, len, txn->sender_euid); handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid); if (!handle) break; bio_put_ref(reply, handle); Loading @@ -294,6 +316,11 @@ 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)) { ALOGE("list_service() uid=%d - PERMISSION DENIED\n", txn->sender_euid); return -1; } si = svclist; while ((n-- > 0) && si) si = si->next; Loading Loading @@ -334,8 +361,21 @@ int main(int argc, char **argv) return -1; } selinux_enabled = is_selinux_enabled(); sehandle = selinux_android_service_context_handle(); if (selinux_enabled > 0) { if (sehandle == NULL) { ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n"); abort(); } if (getcon(&service_manager_context) != 0) { ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n"); abort(); } } union selinux_callback cb; cb.func_audit = audit_callback; selinux_set_callback(SELINUX_CB_AUDIT, cb); Loading