Merge "Fixed an unused param warning in logcat"
diff --git a/init/devices.c b/init/devices.c
index c367de8..597f958 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -33,6 +33,7 @@
 #ifdef HAVE_SELINUX
 #include <selinux/selinux.h>
 #include <selinux/label.h>
+#include <selinux/android.h>
 #endif
 
 #include <private/android_filesystem_config.h>
@@ -871,12 +872,10 @@
     struct stat info;
     int fd;
 #ifdef HAVE_SELINUX
-    struct selinux_opt seopts[] = {
-        { SELABEL_OPT_PATH, "/file_contexts" }
-    };
-
-    if (is_selinux_enabled() > 0)
-        sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);
+    sehandle = NULL;
+    if (is_selinux_enabled() > 0) {
+        sehandle = selinux_android_file_context_handle();
+    }
 #endif
     /* is 64K enough? udev uses 16MB! */
     device_fd = uevent_open_socket(64*1024, true);
diff --git a/init/init.c b/init/init.c
index cc98afc..b2e39bd 100755
--- a/init/init.c
+++ b/init/init.c
@@ -33,9 +33,9 @@
 #include <sys/un.h>
 
 #ifdef HAVE_SELINUX
-#include <sys/mman.h>
 #include <selinux/selinux.h>
 #include <selinux/label.h>
+#include <selinux/android.h>
 #endif
 
 #include <libgen.h>
@@ -61,6 +61,7 @@
 
 #ifdef HAVE_SELINUX
 struct selabel_handle *sehandle;
+struct selabel_handle *sehandle_prop;
 #endif
 
 static int property_triggers_enabled = 0;
@@ -77,7 +78,6 @@
 
 #ifdef HAVE_SELINUX
 static int selinux_enabled = 1;
-static int selinux_enforcing = 0;
 #endif
 
 static struct action *cur_action = NULL;
@@ -604,9 +604,7 @@
     if (name_len == 0) return;
 
 #ifdef HAVE_SELINUX
-    if (!strcmp(name,"enforcing")) {
-        selinux_enforcing = atoi(value);
-    } else if (!strcmp(name,"selinux")) {
+    if (!strcmp(name,"selinux")) {
         selinux_enabled = atoi(value);
     }
 #endif
@@ -758,94 +756,64 @@
 #endif
 
 #ifdef HAVE_SELINUX
-void selinux_load_policy(void)
+static const struct selinux_opt seopts_prop[] = {
+        { SELABEL_OPT_PATH, "/data/system/property_contexts" },
+        { SELABEL_OPT_PATH, "/property_contexts" },
+        { 0, NULL }
+};
+
+struct selabel_handle* selinux_android_prop_context_handle(void)
 {
-    const char path_prefix[] = "/sepolicy";
-    struct selinux_opt seopts[] = {
-        { SELABEL_OPT_PATH, "/file_contexts" }
-    };
-    char path[PATH_MAX];
-    int fd, rc, vers;
-    struct stat sb;
-    void *map;
-
-    sehandle = NULL;
-    if (!selinux_enabled) {
-        INFO("SELinux:  Disabled by command line option\n");
-        return;
+    int i = 0;
+    struct selabel_handle* sehandle = NULL;
+    while ((sehandle == NULL) && seopts_prop[i].value) {
+        sehandle = selabel_open(SELABEL_CTX_ANDROID_PROP, &seopts_prop[i], 1);
+        i++;
     }
 
-    mkdir(SELINUXMNT, 0755);
-    if (mount("selinuxfs", SELINUXMNT, "selinuxfs", 0, NULL)) {
-        if (errno == ENODEV) {
-            /* SELinux not enabled in kernel */
-            return;
-        }
-        ERROR("SELinux:  Could not mount selinuxfs:  %s\n",
-              strerror(errno));
-        return;
-    }
-    set_selinuxmnt(SELINUXMNT);
-
-    vers = security_policyvers();
-    if (vers <= 0) {
-        ERROR("SELinux:  Unable to read policy version\n");
-        return;
-    }
-    INFO("SELinux:  Maximum supported policy version:  %d\n", vers);
-
-    snprintf(path, sizeof(path), "%s.%d",
-             path_prefix, vers);
-    fd = open(path, O_RDONLY);
-    while (fd < 0 && errno == ENOENT && --vers) {
-        snprintf(path, sizeof(path), "%s.%d",
-                 path_prefix, vers);
-        fd = open(path, O_RDONLY);
-    }
-    if (fd < 0) {
-        ERROR("SELinux:  Could not open %s:  %s\n",
-              path, strerror(errno));
-        return;
-    }
-    if (fstat(fd, &sb) < 0) {
-        ERROR("SELinux:  Could not stat %s:  %s\n",
-              path, strerror(errno));
-        return;
-    }
-    map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
-    if (map == MAP_FAILED) {
-        ERROR("SELinux:  Could not map %s:  %s\n",
-              path, strerror(errno));
-        return;
-    }
-
-    rc = security_load_policy(map, sb.st_size);
-    if (rc < 0) {
-        ERROR("SELinux:  Could not load policy:  %s\n",
-              strerror(errno));
-        return;
-    }
-
-    rc = security_setenforce(selinux_enforcing);
-    if (rc < 0) {
-        ERROR("SELinux:  Could not set enforcing mode to %s:  %s\n",
-              selinux_enforcing ? "enforcing" : "permissive", strerror(errno));
-        return;
-    }
-
-    munmap(map, sb.st_size);
-    close(fd);
-    INFO("SELinux: Loaded policy from %s\n", path);
-
-    sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);
     if (!sehandle) {
-        ERROR("SELinux:  Could not load file_contexts:  %s\n",
+        ERROR("SELinux:  Could not load property_contexts:  %s\n",
               strerror(errno));
-        return;
+        return NULL;
     }
-    INFO("SELinux: Loaded file contexts from %s\n", seopts[0].value);
-    return;
+    INFO("SELinux: Loaded property contexts from %s\n", seopts_prop[i - 1].value);
+    return sehandle;
 }
+
+void selinux_init_all_handles(void)
+{
+    sehandle = selinux_android_file_context_handle();
+    sehandle_prop = selinux_android_prop_context_handle();
+}
+
+int selinux_reload_policy(void)
+{
+    if (!selinux_enabled) {
+        return -1;
+    }
+
+    INFO("SELinux: Attempting to reload policy files\n");
+
+    if (selinux_android_reload_policy() == -1) {
+        return -1;
+    }
+
+    if (sehandle)
+        selabel_close(sehandle);
+
+    if (sehandle_prop)
+        selabel_close(sehandle_prop);
+
+    selinux_init_all_handles();
+    return 0;
+}
+
+int audit_callback(void *data, security_class_t cls, char *buf, size_t len)
+{
+    snprintf(buf, len, "property=%s", !data ? "NULL" : (char *)data);
+    return 0;
+}
+
 #endif
 
 int main(int argc, char **argv)
@@ -899,9 +867,25 @@
     process_kernel_cmdline();
 
 #ifdef HAVE_SELINUX
+    union selinux_callback cb;
+    cb.func_log = klog_write;
+    selinux_set_callback(SELINUX_CB_LOG, cb);
+
+    cb.func_audit = audit_callback;
+    selinux_set_callback(SELINUX_CB_AUDIT, cb);
+
     INFO("loading selinux policy\n");
-    selinux_load_policy();
-    /* These directories were necessarily created before policy load
+    if (selinux_enabled) {
+        if (selinux_android_load_policy() < 0) {
+            selinux_enabled = 0;
+            INFO("SELinux: Disabled due to failed policy load\n");
+        } else {
+            selinux_init_all_handles();
+        }
+    } else {
+        INFO("SELinux:  Disabled by command line option\n");
+    }
+    /* These directories were necessarily created before initial policy load
      * and therefore need their security context restored to the proper value.
      * This must happen before /dev is populated by ueventd.
      */
diff --git a/init/init.h b/init/init.h
index 58bbbfe..b7e06c9 100644
--- a/init/init.h
+++ b/init/init.h
@@ -138,6 +138,8 @@
 
 #ifdef HAVE_SELINUX
 extern struct selabel_handle *sehandle;
+extern struct selabel_handle *sehandle_prop;
+extern int selinux_reload_policy(void);
 #endif
 
 #endif	/* _INIT_INIT_H */
diff --git a/init/property_service.c b/init/property_service.c
index 79914cd..5017375 100644
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -40,6 +40,11 @@
 #include <sys/atomics.h>
 #include <private/android_filesystem_config.h>
 
+#ifdef HAVE_SELINUX
+#include <selinux/selinux.h>
+#include <selinux/label.h>
+#endif
+
 #include "property_service.h"
 #include "init.h"
 #include "util.h"
@@ -86,6 +91,7 @@
     { "persist.sys.",     AID_SYSTEM,   0 },
     { "persist.service.", AID_SYSTEM,   0 },
     { "persist.security.", AID_SYSTEM,   0 },
+    { "selinux."         , AID_SYSTEM,   0 },
     { NULL, 0, 0 }
 };
 
@@ -191,23 +197,77 @@
     __futex_wake(&pi->serial, INT32_MAX);
 }
 
+static int check_mac_perms(const char *name, char *sctx)
+{
+#ifdef HAVE_SELINUX
+    if (is_selinux_enabled() <= 0)
+        return 1;
+
+    char *tctx = NULL;
+    const char *class = "property_service";
+    const char *perm = "set";
+    int result = 0;
+
+    if (!sctx)
+        goto err;
+
+    if (!sehandle_prop)
+        goto err;
+
+    if (selabel_lookup(sehandle_prop, &tctx, name, 1) != 0)
+        goto err;
+
+    if (selinux_check_access(sctx, tctx, class, perm, name) == 0)
+        result = 1;
+
+    freecon(tctx);
+ err:
+    return result;
+
+#endif
+    return 1;
+}
+
+static int check_control_mac_perms(const char *name, char *sctx)
+{
+#ifdef HAVE_SELINUX
+
+    /*
+     *  Create a name prefix out of ctl.<service name>
+     *  The new prefix allows the use of the existing
+     *  property service backend labeling while avoiding
+     *  mislabels based on true property prefixes.
+     */
+    char ctl_name[PROP_VALUE_MAX+4];
+    int ret = snprintf(ctl_name, sizeof(ctl_name), "ctl.%s", name);
+
+    if (ret < 0 || (size_t) ret >= sizeof(ctl_name))
+        return 0;
+
+    return check_mac_perms(ctl_name, sctx);
+
+#endif
+    return 1;
+}
+
 /*
  * Checks permissions for starting/stoping system services.
  * AID_SYSTEM and AID_ROOT are always allowed.
  *
  * Returns 1 if uid allowed, 0 otherwise.
  */
-static int check_control_perms(const char *name, unsigned int uid, unsigned int gid) {
+static int check_control_perms(const char *name, unsigned int uid, unsigned int gid, char *sctx) {
+
     int i;
     if (uid == AID_SYSTEM || uid == AID_ROOT)
-        return 1;
+      return check_control_mac_perms(name, sctx);
 
     /* Search the ACL */
     for (i = 0; control_perms[i].service; i++) {
         if (strcmp(control_perms[i].service, name) == 0) {
             if ((uid && control_perms[i].uid == uid) ||
                 (gid && control_perms[i].gid == gid)) {
-                return 1;
+                return check_control_mac_perms(name, sctx);
             }
         }
     }
@@ -218,22 +278,22 @@
  * Checks permissions for setting system properties.
  * Returns 1 if uid allowed, 0 otherwise.
  */
-static int check_perms(const char *name, unsigned int uid, unsigned int gid)
+static int check_perms(const char *name, unsigned int uid, unsigned int gid, char *sctx)
 {
     int i;
-    if (uid == 0)
-        return 1;
-
     if(!strncmp(name, "ro.", 3))
         name +=3;
 
+    if (uid == 0)
+        return check_mac_perms(name, sctx);
+
     for (i = 0; property_perms[i].prefix; i++) {
-        int tmp;
         if (strncmp(property_perms[i].prefix, name,
                     strlen(property_perms[i].prefix)) == 0) {
             if ((uid && property_perms[i].uid == uid) ||
                 (gid && property_perms[i].gid == gid)) {
-                return 1;
+
+                return check_mac_perms(name, sctx);
             }
         }
     }
@@ -334,6 +394,11 @@
          * to prevent them from being overwritten by default values.
          */
         write_persistent_property(name, value);
+#ifdef HAVE_SELINUX
+    } else if (strcmp("selinux.reload_policy", name) == 0 &&
+               strcmp("1", value) == 0) {
+        selinux_reload_policy();
+#endif
     }
     property_changed(name, value);
     return 0;
@@ -349,6 +414,7 @@
     struct sockaddr_un addr;
     socklen_t addr_size = sizeof(addr);
     socklen_t cr_size = sizeof(cr);
+    char * source_ctx = NULL;
 
     if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) {
         return;
@@ -374,18 +440,22 @@
         msg.name[PROP_NAME_MAX-1] = 0;
         msg.value[PROP_VALUE_MAX-1] = 0;
 
+#ifdef HAVE_SELINUX
+        getpeercon(s, &source_ctx);
+#endif
+
         if(memcmp(msg.name,"ctl.",4) == 0) {
             // Keep the old close-socket-early behavior when handling
             // ctl.* properties.
             close(s);
-            if (check_control_perms(msg.value, cr.uid, cr.gid)) {
+            if (check_control_perms(msg.value, cr.uid, cr.gid, source_ctx)) {
                 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, cr.uid, cr.gid)) {
+            if (check_perms(msg.name, cr.uid, cr.gid, source_ctx)) {
                 property_set((char*) msg.name, (char*) msg.value);
             } else {
                 ERROR("sys_prop: permission denied uid:%d  name:%s\n",
@@ -397,6 +467,10 @@
             // the property is written to memory.
             close(s);
         }
+#ifdef HAVE_SELINUX
+        freecon(source_ctx);
+#endif
+
         break;
 
     default:
diff --git a/libzipfile/centraldir.c b/libzipfile/centraldir.c
index 0e264a3..911e2b9 100644
--- a/libzipfile/centraldir.c
+++ b/libzipfile/centraldir.c
@@ -192,7 +192,7 @@
 

     // too small to be a ZIP archive?

     if (bufsize < EOCD_LEN) {

-        fprintf(stderr, "Length is %d -- too small\n", bufsize);

+        fprintf(stderr, "Length is %zd -- too small\n", bufsize);

         goto bail;

     }

 

diff --git a/rootdir/init.rc b/rootdir/init.rc
index 054c2ca..6a0c332 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -355,6 +355,10 @@
     critical
     seclabel u:r:ueventd:s0
 
+on property:selinux.reload_policy=1
+    restart ueventd
+    restart installd
+
 service console /system/bin/sh
     class core
     console
diff --git a/toolbox/restorecon.c b/toolbox/restorecon.c
index 5ef0ef1..f9f604f 100644
--- a/toolbox/restorecon.c
+++ b/toolbox/restorecon.c
@@ -7,8 +7,7 @@
 #include <fts.h>
 #include <selinux/selinux.h>
 #include <selinux/label.h>
-
-#define FCPATH "/file_contexts"
+#include <selinux/android.h>
 
 static struct selabel_handle *sehandle;
 static const char *progname;
@@ -17,7 +16,7 @@
 
 static void usage(void)
 {
-    fprintf(stderr, "usage:  %s [-f file_contexts] [-nrRv] pathname...\n", progname);
+    fprintf(stderr, "usage:  %s [-nrRv] pathname...\n", progname);
     exit(1);
 }
 
@@ -54,21 +53,16 @@
 
 int restorecon_main(int argc, char **argv)
 {
-    struct selinux_opt seopts[] = {
-        { SELABEL_OPT_PATH, FCPATH }
-    };
     int ch, recurse = 0, ftsflags = FTS_PHYSICAL;
+    int i = 0;
 
     progname = argv[0];
 
     do {
-        ch = getopt(argc, argv, "f:nrRv");
+        ch = getopt(argc, argv, "nrRv");
         if (ch == EOF)
             break;
         switch (ch) {
-        case 'f':
-            seopts[0].value = optarg;
-            break;
         case 'n':
             nochange = 1;
             break;
@@ -89,9 +83,10 @@
     if (!argc)
         usage();
 
-    sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);
+    sehandle = selinux_android_file_context_handle();
+
     if (!sehandle) {
-        fprintf(stderr, "Could not load file contexts from %s:  %s\n", seopts[0].value,
+        fprintf(stderr, "Could not load file_contexts:  %s\n",
                 strerror(errno));
         return -1;
     }