Add service_context management into libselinux.

Add functions to handle opening handles for MAC
on service_manager. Also add selinux_log_callback
into libselinux because identical code was spread
through three different files.

Bug: 12909011
Change-Id: I04eb855700f1d0c086542053d987b3a30cf1b0c0
diff --git a/Android.mk b/Android.mk
index baec088..7abb19c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -72,4 +72,5 @@
 LOCAL_COPY_HEADERS := $(common_COPY_HEADERS)
 LOCAL_PRELINK_MODULE := false
 LOCAL_STATIC_LIBRARIES := libmincrypt
+LOCAL_SHARED_LIBRARIES := liblog
 include $(BUILD_SHARED_LIBRARY)
diff --git a/include/selinux/android.h b/include/selinux/android.h
index ae6c05d..00894f5 100644
--- a/include/selinux/android.h
+++ b/include/selinux/android.h
@@ -13,6 +13,8 @@
 
 extern struct selabel_handle* selinux_android_file_context_handle(void);
 
+extern struct selabel_handle* selinux_android_service_context_handle(void);
+
 extern void selinux_android_set_sehandle(const struct selabel_handle *hndl);
 
 extern int selinux_android_load_policy(void);
@@ -29,6 +31,9 @@
 				       const char *seinfo,
 				       uid_t uid);
 
+extern int selinux_log_callback(int type, const char *fmt, ...)
+    __attribute__ ((format(printf, 2, 3)));
+
 #define SELINUX_ANDROID_RESTORECON_NOCHANGE 1
 #define SELINUX_ANDROID_RESTORECON_VERBOSE  2
 #define SELINUX_ANDROID_RESTORECON_RECURSE  4
diff --git a/src/android.c b/src/android.c
index d0432d4..ffb2adb 100644
--- a/src/android.c
+++ b/src/android.c
@@ -22,6 +22,7 @@
 #include <selinux/avc.h>
 #include <mincrypt/sha.h>
 #include <private/android_filesystem_config.h>
+#include <log/log.h>
 #include "policy.h"
 #include "callbacks.h"
 #include "selinux_internal.h"
@@ -48,6 +49,12 @@
 	"/data/security/current/sepolicy",
 	NULL };
 
+static const struct selinux_opt seopts_service[] = {
+    { SELABEL_OPT_PATH, "/service_contexts" },
+    { SELABEL_OPT_PATH, "/data/security/current/service_contexts" },
+    { 0, NULL }
+};
+
 enum levelFrom {
 	LEVELFROM_NONE,
 	LEVELFROM_APP,
@@ -859,6 +866,25 @@
         sehandle = file_context_open();
 }
 
+static struct selabel_handle *service_context_open(void)
+{
+    struct selabel_handle *handle = NULL;
+
+    set_policy_index();
+    handle = selabel_open(SELABEL_CTX_ANDROID_PROP,
+            &seopts_service[policy_index], 1);
+
+    if (!handle) {
+        selinux_log(SELINUX_ERROR, "%s: Error getting service context handle (%s)\n",
+                __FUNCTION__, strerror(errno));
+    } else {
+        selinux_log(SELINUX_INFO, "SELinux: Loaded service contexts from %s.\n",
+                seopts_service[policy_index].value);
+    }
+
+    return handle;
+}
+
 static pthread_once_t fc_once = PTHREAD_ONCE_INIT;
 
 struct pkgInfo {
@@ -1282,6 +1308,11 @@
     return file_context_open();
 }
 
+struct selabel_handle* selinux_android_service_context_handle(void)
+{
+    return service_context_open();
+}
+
 void selinux_android_set_sehandle(const struct selabel_handle *hndl)
 {
     sehandle = (struct selabel_handle *) hndl;
@@ -1374,3 +1405,26 @@
 
     return selinux_android_load_policy_helper(false);
 }
+
+int selinux_log_callback(int type, const char *fmt, ...)
+{
+    va_list ap;
+    int priority;
+
+    switch(type) {
+    case SELINUX_WARNING:
+        priority = ANDROID_LOG_WARN;
+        break;
+    case SELINUX_INFO:
+        priority = ANDROID_LOG_INFO;
+        break;
+    default:
+        priority = ANDROID_LOG_ERROR;
+        break;
+    }
+
+    va_start(ap, fmt);
+    LOG_PRI_VA(priority, "SELinux", fmt, ap);
+    va_end(ap);
+    return 0;
+}