Implement SELinux/MAC checks for property service.

This is a set of changes to the init property service
implementation to apply a SELinux check over who can
change what properties. Also included control hooks
for the 'ctl' keys.

Change-Id: I5a18809bf5536f6459a36b6bf0d622b9f5061aa0
Signed-off-by: rpcraig <rpcraig@tycho.ncsc.mil>
diff --git a/init/init.c b/init/init.c
index d11db61..b2e39bd 100755
--- a/init/init.c
+++ b/init/init.c
@@ -61,6 +61,7 @@
 
 #ifdef HAVE_SELINUX
 struct selabel_handle *sehandle;
+struct selabel_handle *sehandle_prop;
 #endif
 
 static int property_triggers_enabled = 0;
@@ -755,9 +756,34 @@
 #endif
 
 #ifdef HAVE_SELINUX
+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)
+{
+    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++;
+    }
+
+    if (!sehandle) {
+        ERROR("SELinux:  Could not load property_contexts:  %s\n",
+              strerror(errno));
+        return NULL;
+    }
+    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)
@@ -775,9 +801,19 @@
     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)
@@ -831,6 +867,13 @@
     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");
     if (selinux_enabled) {
         if (selinux_android_load_policy() < 0) {