OSDN Git Service

Adds Zygote.initNativeState
authorChris Wailes <chriswailes@google.com>
Wed, 3 Apr 2019 20:00:52 +0000 (13:00 -0700)
committerChris Wailes <chriswailes@google.com>
Wed, 3 Apr 2019 20:42:35 +0000 (13:42 -0700)
This patch replaces three seperate native initialization functions with
a single function, reducing the number of times we need to cross the JNI
boundary.  In addition this loads an empty performance profile for the
zygote to address b/129704892.

Bug: 129704892
Test: make & boot
Test: Treehugger
Change-Id: I0413f554e0963a714e0b4de3196d31ffe6775a3a

core/java/com/android/internal/os/Zygote.java
core/java/com/android/internal/os/ZygoteInit.java
core/jni/com_android_internal_os_Zygote.cpp

index 8ca0bd1..afdeb1b 100644 (file)
@@ -197,9 +197,6 @@ public final class Zygote {
 
     private Zygote() {}
 
-    /** Called for some security initialization before any fork. */
-    static native void nativeSecurityInit();
-
     /**
      * Forks a new VM instance.  The current VM must have been started
      * with the -Xzygote flag. <b>NOTE: new instance keeps all
@@ -384,22 +381,19 @@ public final class Zygote {
     native protected static void nativeInstallSeccompUidGidFilter(int uidGidMin, int uidGidMax);
 
     /**
-     * Zygote unmount storage space on initializing.
-     * This method is called once.
-     */
-    protected static native void nativeUnmountStorageOnInit();
-
-    /**
-     * Get socket file descriptors (opened by init) from the environment and
-     * store them for access from native code later.
+     * Initialize the native state of the Zygote.  This inclues
+     *   - Fetching socket FDs from the environment
+     *   - Initializing security properties
+     *   - Unmounting storage as appropriate
+     *   - Loading necessary performance profile information
      *
      * @param isPrimary  True if this is the zygote process, false if it is zygote_secondary
      */
-    public static void getSocketFDs(boolean isPrimary) {
-        nativeGetSocketFDs(isPrimary);
+    static void initNativeState(boolean isPrimary) {
+        nativeInitNativeState(isPrimary);
     }
 
-    protected static native void nativeGetSocketFDs(boolean isPrimary);
+    protected static native void nativeInitNativeState(boolean isPrimary);
 
     /**
      * Returns the raw string value of a system property.
index 7cca7b7..bb7b09a 100644 (file)
@@ -20,10 +20,10 @@ import static android.system.OsConstants.S_IRWXG;
 import static android.system.OsConstants.S_IRWXO;
 
 import android.annotation.UnsupportedAppUsage;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
 import android.app.ApplicationLoaders;
 import android.content.pm.SharedLibraryInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.os.Build;
 import android.os.Environment;
 import android.os.IInstalld;
@@ -863,8 +863,6 @@ public class ZygoteInit {
                 throw new RuntimeException("No ABI list supplied.");
             }
 
-            Zygote.getSocketFDs(isPrimaryZygote);
-
             // In some configurations, we avoid preloading resources and classes eagerly.
             // In such cases, we will preload things prior to our first fork.
             if (!enableLazyPreload) {
@@ -889,10 +887,8 @@ public class ZygoteInit {
             // Zygote.
             Trace.setTracingEnabled(false, 0);
 
-            Zygote.nativeSecurityInit();
 
-            // Zygote process unmounts root storage spaces.
-            Zygote.nativeUnmountStorageOnInit();
+            Zygote.initNativeState(isPrimaryZygote);
 
             ZygoteHooks.stopZygoteNoThreadCreation();
 
index 8dd7e8e..430b9c5 100644 (file)
@@ -126,7 +126,7 @@ static constexpr const char* kZygoteInitClassName = "com/android/internal/os/Zyg
 static jclass gZygoteInitClass;
 static jmethodID gCreateSystemServerClassLoader;
 
-static bool g_is_security_enforced = true;
+static bool gIsSecurityEnforced = true;
 
 /**
  * The maximum number of characters (not including a null terminator) that a
@@ -510,7 +510,7 @@ static void PreApplicationInit() {
 }
 
 static void SetUpSeccompFilter(uid_t uid, bool is_child_zygote) {
-  if (!g_is_security_enforced) {
+  if (!gIsSecurityEnforced) {
     ALOGI("seccomp disabled by setenforce 0");
     return;
   }
@@ -1626,18 +1626,48 @@ std::vector<int> MakeUsapPipeReadFDVector() {
   return fd_vec;
 }
 
-}  // anonymous namespace
+static void UnmountStorageOnInit(JNIEnv* env) {
+  // Zygote process unmount root storage space initially before every child processes are forked.
+  // Every forked child processes (include SystemServer) only mount their own root storage space
+  // and no need unmount storage operation in MountEmulatedStorage method.
+  // Zygote process does not utilize root storage spaces and unshares its mount namespace below.
 
-namespace android {
+  // See storage config details at http://source.android.com/tech/storage/
+  // Create private mount namespace shared by all children
+  if (unshare(CLONE_NEWNS) == -1) {
+    RuntimeAbort(env, __LINE__, "Failed to unshare()");
+    return;
+  }
 
-static void com_android_internal_os_Zygote_nativeSecurityInit(JNIEnv*, jclass) {
-  // security_getenforce is not allowed on app process. Initialize and cache
-  // the value before zygote forks.
-  g_is_security_enforced = security_getenforce();
+  // Mark rootfs as being a slave so that changes from default
+  // namespace only flow into our children.
+  if (mount("rootfs", "/", nullptr, (MS_SLAVE | MS_REC), nullptr) == -1) {
+    RuntimeAbort(env, __LINE__, "Failed to mount() rootfs as MS_SLAVE");
+    return;
+  }
 
-  selinux_android_seapp_context_init();
+  // Create a staging tmpfs that is shared by our children; they will
+  // bind mount storage into their respective private namespaces, which
+  // are isolated from each other.
+  const char* target_base = getenv("EMULATED_STORAGE_TARGET");
+  if (target_base != nullptr) {
+#define STRINGIFY_UID(x) __STRING(x)
+    if (mount("tmpfs", target_base, "tmpfs", MS_NOSUID | MS_NODEV,
+              "uid=0,gid=" STRINGIFY_UID(AID_SDCARD_R) ",mode=0751") == -1) {
+      ALOGE("Failed to mount tmpfs to %s", target_base);
+      RuntimeAbort(env, __LINE__, "Failed to mount tmpfs");
+      return;
+    }
+#undef STRINGIFY_UID
+  }
+
+  UnmountTree("/storage");
 }
 
+}  // anonymous namespace
+
+namespace android {
+
 static void com_android_internal_os_Zygote_nativePreApplicationInit(JNIEnv*, jclass) {
   PreApplicationInit();
 }
@@ -1791,47 +1821,9 @@ static void com_android_internal_os_Zygote_nativeAllowFileAcrossFork(
     FileDescriptorWhitelist::Get()->Allow(path_cstr);
 }
 
-static void com_android_internal_os_Zygote_nativeUnmountStorageOnInit(JNIEnv* env, jclass) {
-    // Zygote process unmount root storage space initially before every child processes are forked.
-    // Every forked child processes (include SystemServer) only mount their own root storage space
-    // and no need unmount storage operation in MountEmulatedStorage method.
-    // Zygote process does not utilize root storage spaces and unshares its mount namespace below.
-
-    // See storage config details at http://source.android.com/tech/storage/
-    // Create private mount namespace shared by all children
-    if (unshare(CLONE_NEWNS) == -1) {
-        RuntimeAbort(env, __LINE__, "Failed to unshare()");
-        return;
-    }
-
-    // Mark rootfs as being a slave so that changes from default
-    // namespace only flow into our children.
-    if (mount("rootfs", "/", nullptr, (MS_SLAVE | MS_REC), nullptr) == -1) {
-        RuntimeAbort(env, __LINE__, "Failed to mount() rootfs as MS_SLAVE");
-        return;
-    }
-
-    // Create a staging tmpfs that is shared by our children; they will
-    // bind mount storage into their respective private namespaces, which
-    // are isolated from each other.
-    const char* target_base = getenv("EMULATED_STORAGE_TARGET");
-    if (target_base != nullptr) {
-#define STRINGIFY_UID(x) __STRING(x)
-        if (mount("tmpfs", target_base, "tmpfs", MS_NOSUID | MS_NODEV,
-                  "uid=0,gid=" STRINGIFY_UID(AID_SDCARD_R) ",mode=0751") == -1) {
-            ALOGE("Failed to mount tmpfs to %s", target_base);
-            RuntimeAbort(env, __LINE__, "Failed to mount tmpfs");
-            return;
-        }
-#undef STRINGIFY_UID
-    }
-
-    UnmountTree("/storage");
-}
-
 static void com_android_internal_os_Zygote_nativeInstallSeccompUidGidFilter(
         JNIEnv* env, jclass, jint uidGidMin, jint uidGidMax) {
-  if (!g_is_security_enforced) {
+  if (!gIsSecurityEnforced) {
     ALOGI("seccomp disabled by setenforce 0");
     return;
   }
@@ -1883,8 +1875,12 @@ static void com_android_internal_os_Zygote_nativeSpecializeAppProcess(
  * @param is_primary  If this process is the primary or secondary Zygote; used to compute the name
  * of the environment variable storing the file descriptors.
  */
-static void com_android_internal_os_Zygote_nativeGetSocketFDs(JNIEnv* env, jclass,
-                                                              jboolean is_primary) {
+static void com_android_internal_os_Zygote_nativeInitNativeState(JNIEnv* env, jclass,
+                                                                 jboolean is_primary) {
+  /*
+   * Obtain file descriptors created by init from the environment.
+   */
+
   std::string android_socket_prefix(ANDROID_SOCKET_PREFIX);
   std::string env_var_name = android_socket_prefix + (is_primary ? "zygote" : "zygote_secondary");
   char* env_var_val = getenv(env_var_name.c_str());
@@ -1905,6 +1901,30 @@ static void com_android_internal_os_Zygote_nativeGetSocketFDs(JNIEnv* env, jclas
   } else {
     ALOGE("Unable to fetch USAP pool socket file descriptor");
   }
+
+  /*
+   * Security Initialization
+   */
+
+  // security_getenforce is not allowed on app process. Initialize and cache
+  // the value before zygote forks.
+  gIsSecurityEnforced = security_getenforce();
+
+  selinux_android_seapp_context_init();
+
+  /*
+   * Storage Initialization
+   */
+
+  UnmountStorageOnInit(env);
+
+  /*
+   * Performance Initialization
+   */
+
+  if (!SetTaskProfiles(0, {})) {
+    ZygoteFailure(env, "zygote", nullptr, "Zygote SetTaskProfiles failed");
+  }
 }
 
 /**
@@ -2001,8 +2021,6 @@ static jboolean com_android_internal_os_Zygote_nativeDisableExecuteOnly(JNIEnv*
 }
 
 static const JNINativeMethod gMethods[] = {
-    { "nativeSecurityInit", "()V",
-      (void *) com_android_internal_os_Zygote_nativeSecurityInit },
     { "nativeForkAndSpecialize",
       "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)I",
       (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
@@ -2010,8 +2028,6 @@ static const JNINativeMethod gMethods[] = {
       (void *) com_android_internal_os_Zygote_nativeForkSystemServer },
     { "nativeAllowFileAcrossFork", "(Ljava/lang/String;)V",
       (void *) com_android_internal_os_Zygote_nativeAllowFileAcrossFork },
-    { "nativeUnmountStorageOnInit", "()V",
-      (void *) com_android_internal_os_Zygote_nativeUnmountStorageOnInit },
     { "nativePreApplicationInit", "()V",
       (void *) com_android_internal_os_Zygote_nativePreApplicationInit },
     { "nativeInstallSeccompUidGidFilter", "(II)V",
@@ -2021,8 +2037,8 @@ static const JNINativeMethod gMethods[] = {
     { "nativeSpecializeAppProcess",
       "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V",
       (void *) com_android_internal_os_Zygote_nativeSpecializeAppProcess },
-    { "nativeGetSocketFDs", "(Z)V",
-      (void *) com_android_internal_os_Zygote_nativeGetSocketFDs },
+    { "nativeInitNativeState", "(Z)V",
+      (void *) com_android_internal_os_Zygote_nativeInitNativeState },
     { "nativeGetUsapPipeFDs", "()[I",
       (void *) com_android_internal_os_Zygote_nativeGetUsapPipeFDs },
     { "nativeRemoveUsapTableEntry", "(I)Z",