summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Kralevich <nnk@google.com>2014-06-12 21:06:37 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2014-06-12 21:06:37 +0000
commit9f12f80d4af350789a64f5c30531ce790d9b6ea3 (patch)
tree062198c11e314e4363275db6ad04ed48c72e88f3
parent20914f0ad3691d977f61f1d4b92b49535e8f6f33 (diff)
parent18c9394ce1a4869eb5cf91eece02a4e944e2eebc (diff)
downloadframeworks_native-9f12f80d4af350789a64f5c30531ce790d9b6ea3.zip
frameworks_native-9f12f80d4af350789a64f5c30531ce790d9b6ea3.tar.gz
frameworks_native-9f12f80d4af350789a64f5c30531ce790d9b6ea3.tar.bz2
am 18c9394c: Merge "Add SELinux checks when adding a service."
* commit '18c9394ce1a4869eb5cf91eece02a4e944e2eebc': Add SELinux checks when adding a service.
-rw-r--r--cmds/servicemanager/Android.mk2
-rw-r--r--cmds/servicemanager/service_manager.c90
2 files changed, 85 insertions, 7 deletions
diff --git a/cmds/servicemanager/Android.mk b/cmds/servicemanager/Android.mk
index 4ab8df6..155cfc5 100644
--- a/cmds/servicemanager/Android.mk
+++ b/cmds/servicemanager/Android.mk
@@ -18,7 +18,7 @@ LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
-LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SHARED_LIBRARIES := liblog libselinux
LOCAL_SRC_FILES := service_manager.c binder.c
LOCAL_CFLAGS += $(svc_c_flags)
LOCAL_MODULE := servicemanager
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 79ce6ed..939920a 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -8,6 +8,8 @@
#include <private/android_filesystem_config.h>
+#include <selinux/android.h>
+
#include "binder.h"
#if 0
@@ -76,16 +78,67 @@ int str16eq(const uint16_t *a, const char *b)
return 1;
}
-int svc_can_register(uid_t uid, const uint16_t *name)
+static struct selabel_handle* sehandle;
+
+static bool check_mac_perms(const char *name, pid_t spid)
+{
+ if (is_selinux_enabled() <= 0) {
+ return true;
+ }
+
+ bool allowed = false;
+
+ const char *class = "service_manager";
+ const char *perm = "add";
+
+ char *tctx = NULL;
+ char *sctx = NULL;
+
+ if (!sehandle) {
+ ALOGE("SELinux: Failed to find sehandle %s.\n", name);
+ return false;
+ }
+
+ if (getpidcon(spid, &sctx) < 0) {
+ ALOGE("SELinux: getpidcon failed to retrieve pid context.\n");
+ return false;
+ }
+
+ if (!sctx) {
+ ALOGE("SELinux: Failed to find sctx for %s.\n", name);
+ return false;
+ }
+
+ 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 (!tctx) {
+ ALOGE("SELinux: Failed to find tctx for %s.\n", name);
+ freecon(sctx);
+ return false;
+ }
+
+ int result = selinux_check_access(sctx, tctx, class, perm, (void *) name);
+ allowed = (result == 0);
+
+ freecon(sctx);
+ freecon(tctx);
+ return allowed;
+}
+
+static int svc_can_register(uid_t uid, const uint16_t *name, pid_t spid)
{
size_t n;
if ((uid == 0) || (uid == AID_SYSTEM))
- return 1;
+ return check_mac_perms(str8(name), spid) ? 1 : 0;
for (n = 0; n < sizeof(allowed) / sizeof(allowed[0]); n++)
if ((uid == allowed[n].uid) && str16eq(name, allowed[n].name))
- return 1;
+ return check_mac_perms(str8(name), spid) ? 1 : 0;
return 0;
}
@@ -155,7 +208,8 @@ uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len,
int do_add_service(struct binder_state *bs,
const uint16_t *s, size_t len,
- uint32_t handle, uid_t uid, int allow_isolated)
+ uint32_t handle, uid_t uid, int allow_isolated,
+ pid_t spid)
{
struct svcinfo *si;
@@ -165,7 +219,7 @@ int do_add_service(struct binder_state *bs,
if (!handle || (len == 0) || (len > 127))
return -1;
- if (!svc_can_register(uid, s)) {
+ if (!svc_can_register(uid, s, spid)) {
ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
str8(s), handle, uid);
return -1;
@@ -235,6 +289,14 @@ int svcmgr_handler(struct binder_state *bs,
return -1;
}
+ if (sehandle && selinux_status_updated() > 0) {
+ struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
+ if (tmp_sehandle) {
+ selabel_close(sehandle);
+ sehandle = tmp_sehandle;
+ }
+ }
+
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
@@ -249,7 +311,8 @@ int svcmgr_handler(struct binder_state *bs,
s = bio_get_string16(msg, &len);
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
- if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated))
+ if (do_add_service(bs, s, len, handle, txn->sender_euid,
+ allow_isolated, txn->sender_pid))
return -1;
break;
@@ -274,6 +337,13 @@ int svcmgr_handler(struct binder_state *bs,
return 0;
}
+
+static int audit_callback(void *data, security_class_t cls, char *buf, size_t len)
+{
+ snprintf(buf, len, "service=%s", !data ? "NULL" : (char *)data);
+ return 0;
+}
+
int main(int argc, char **argv)
{
struct binder_state *bs;
@@ -289,6 +359,14 @@ int main(int argc, char **argv)
return -1;
}
+ sehandle = selinux_android_service_context_handle();
+
+ union selinux_callback cb;
+ 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);
+
svcmgr_handle = BINDER_SERVICE_MANAGER;
binder_loop(bs, svcmgr_handler);