am c4db5ece: am 8e0c88ea: Merge "servicemanager: log pid and uid on selinux denial"

* commit 'c4db5ece1b34ada975041c167215d41a58f788ca':
  servicemanager: log pid and uid on selinux denial
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 7fa9a39..8596f96 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 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 @@
         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 @@
         }
     }
 
-    if (!svc_can_find(s, len, spid)) {
+    if (!svc_can_find(s, len, spid, uid)) {
         return 0;
     }
 
@@ -204,7 +215,7 @@
     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 @@
     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 @@
 
 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;
 }