Extend init and ueventd for SE Android.

Add SE Android support for init and ueventd.

init:
- Load policy at boot.
- Set the security context for service daemons and their sockets.
- New built-in commands: setcon, setenforce, restorecon, setsebool.
- New option for services: seclabel.

ueventd:
- Set the security context for device directories and nodes.

Change-Id: I98ed752cde503c94d99dfa5b5a47e3c33db16aac
diff --git a/init/builtins.c b/init/builtins.c
index 3781dcd..9aa2345 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -33,6 +33,11 @@
 #include <cutils/partition_utils.h>
 #include <sys/system_properties.h>
 
+#ifdef HAVE_SELINUX
+#include <selinux/selinux.h>
+#include <selinux/label.h>
+#endif
+
 #include "init.h"
 #include "keywords.h"
 #include "property_service.h"
@@ -436,6 +441,28 @@
 
 }
 
+int do_setcon(int nargs, char **args) {
+#ifdef HAVE_SELINUX
+    if (is_selinux_enabled() <= 0)
+        return 0;
+    if (setcon(args[1]) < 0) {
+        return -errno;
+    }
+#endif
+    return 0;
+}
+
+int do_setenforce(int nargs, char **args) {
+#ifdef HAVE_SELINUX
+    if (is_selinux_enabled() <= 0)
+        return 0;
+    if (security_setenforce(atoi(args[1])) < 0) {
+        return -errno;
+    }
+#endif
+    return 0;
+}
+
 int do_setkey(int nargs, char **args)
 {
     struct kbentry kbe;
@@ -649,6 +676,64 @@
     return 0;
 }
 
+int do_restorecon(int nargs, char **args) {
+#ifdef HAVE_SELINUX
+    char *secontext = NULL;
+    struct stat sb;
+    int i;
+
+    if (is_selinux_enabled() <= 0 || !sehandle)
+        return 0;
+
+    for (i = 1; i < nargs; i++) {
+        if (lstat(args[i], &sb) < 0)
+            return -errno;
+        if (selabel_lookup(sehandle, &secontext, args[i], sb.st_mode) < 0)
+            return -errno;
+        if (lsetfilecon(args[i], secontext) < 0) {
+            freecon(secontext);
+            return -errno;
+        }
+        freecon(secontext);
+    }
+#endif
+    return 0;
+}
+
+int do_setsebool(int nargs, char **args) {
+#ifdef HAVE_SELINUX
+    SELboolean *b = alloca(nargs * sizeof(SELboolean));
+    char *v;
+    int i;
+
+    if (is_selinux_enabled() <= 0)
+        return 0;
+
+    for (i = 1; i < nargs; i++) {
+        char *name = args[i];
+        v = strchr(name, '=');
+        if (!v) {
+            ERROR("setsebool: argument %s had no =\n", name);
+            return -EINVAL;
+        }
+        *v++ = 0;
+        b[i-1].name = name;
+        if (!strcmp(v, "1") || !strcasecmp(v, "true") || !strcasecmp(v, "on"))
+            b[i-1].value = 1;
+        else if (!strcmp(v, "0") || !strcasecmp(v, "false") || !strcasecmp(v, "off"))
+            b[i-1].value = 0;
+        else {
+            ERROR("setsebool: invalid value %s\n", v);
+            return -EINVAL;
+        }
+    }
+
+    if (security_set_boolean_list(nargs - 1, b, 0) < 0)
+        return -errno;
+#endif
+    return 0;
+}
+
 int do_loglevel(int nargs, char **args) {
     if (nargs == 2) {
         klog_set_level(atoi(args[1]));