Merge "Extend forkAndSpecialize to take additional inputs and to set the SELinux security context."
diff --git a/vm/ReconfigureDvm.mk b/vm/ReconfigureDvm.mk
index 20e5626..09fbb5d 100644
--- a/vm/ReconfigureDvm.mk
+++ b/vm/ReconfigureDvm.mk
@@ -28,6 +28,12 @@
 
 LOCAL_SHARED_LIBRARIES += liblog libcutils libnativehelper libz libdl
 
+ifeq ($(HAVE_SELINUX),true)
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_SHARED_LIBRARIES += libselinux
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif # HAVE_SELINUX
+
 LOCAL_STATIC_LIBRARIES += libdex
 
 LOCAL_C_INCLUDES += external/stlport/stlport bionic/ bionic/libstdc++/include
diff --git a/vm/native/dalvik_system_Zygote.cpp b/vm/native/dalvik_system_Zygote.cpp
index 492ea4a..e5ba597 100644
--- a/vm/native/dalvik_system_Zygote.cpp
+++ b/vm/native/dalvik_system_Zygote.cpp
@@ -20,6 +20,10 @@
 #include "Dalvik.h"
 #include "native/InternalNativePriv.h"
 
+#ifdef HAVE_SELINUX
+#include <selinux/android.h>
+#endif
+
 #include <signal.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -356,6 +360,23 @@
     return 0;
 }
 
+#ifdef HAVE_SELINUX
+/*
+ * Set SELinux security context.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+static int setSELinuxContext(uid_t uid, bool isSystemServer,
+                             const char *seInfo, const char *niceName)
+{
+#ifdef HAVE_ANDROID_OS
+    return selinux_android_setcontext(uid, isSystemServer, seInfo, niceName);
+#else
+    return 0;
+#endif
+}
+#endif
+
 /*
  * Utility routine to fork zygote and specialize the child process.
  */
@@ -369,6 +390,10 @@
     u4 debugFlags = args[3];
     ArrayObject *rlimits = (ArrayObject *)args[4];
     int64_t permittedCapabilities, effectiveCapabilities;
+#ifdef HAVE_SELINUX
+    char *seInfo = NULL;
+    char *niceName = NULL;
+#endif
 
     if (isSystemServer) {
         /*
@@ -382,6 +407,24 @@
         effectiveCapabilities = args[7] | (int64_t) args[8] << 32;
     } else {
         permittedCapabilities = effectiveCapabilities = 0;
+#ifdef HAVE_SELINUX
+        StringObject* seInfoObj = (StringObject*)args[5];
+        if (seInfoObj) {
+            seInfo = dvmCreateCstrFromString(seInfoObj);
+            if (!seInfo) {
+                LOGE("seInfo dvmCreateCstrFromString failed");
+                dvmAbort();
+            }
+        }
+        StringObject* niceNameObj = (StringObject*)args[6];
+        if (niceNameObj) {
+            niceName = dvmCreateCstrFromString(niceNameObj);
+            if (!niceName) {
+                LOGE("niceName dvmCreateCstrFromString failed");
+                dvmAbort();
+            }
+        }
+#endif
     }
 
     if (!gDvm.zygote) {
@@ -460,6 +503,16 @@
             dvmAbort();
         }
 
+#ifdef HAVE_SELINUX
+        err = setSELinuxContext(uid, isSystemServer, seInfo, niceName);
+        if (err < 0) {
+            LOGE("cannot set SELinux context: %s\n", strerror(errno));
+            dvmAbort();
+        }
+        free(seInfo);
+        free(niceName);
+#endif
+
         /*
          * Our system thread ID has changed.  Get the new one.
          */
@@ -477,13 +530,17 @@
         }
     } else if (pid > 0) {
         /* the parent process */
+#ifdef HAVE_SELINUX
+        free(seInfo);
+        free(niceName);
+#endif
     }
 
     return pid;
 }
 
 /* native public static int forkAndSpecialize(int uid, int gid,
- *     int[] gids, int debugFlags);
+ *     int[] gids, int debugFlags, String seInfo, String niceName);
  */
 static void Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4* args,
     JValue* pResult)
@@ -542,7 +599,7 @@
 const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {
     { "nativeFork", "()I",
       Dalvik_dalvik_system_Zygote_fork },
-    { "nativeForkAndSpecialize", "(II[II[[I)I",
+    { "nativeForkAndSpecialize", "(II[II[[ILjava/lang/String;Ljava/lang/String;)I",
       Dalvik_dalvik_system_Zygote_forkAndSpecialize },
     { "nativeForkSystemServer", "(II[II[[IJJ)I",
       Dalvik_dalvik_system_Zygote_forkSystemServer },