summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java29
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp24
2 files changed, 48 insertions, 5 deletions
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 6ff656c3f8db..0f26f57e2155 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -127,6 +127,12 @@ public class ZygoteInit {
private static boolean sPreloadComplete;
+ /**
+ * Cached classloader to use for the system server. Will only be populated in the system
+ * server process.
+ */
+ private static ClassLoader sCachedSystemServerClassLoader = null;
+
static void preload(TimingsTraceLog bootTimingsTraceLog) {
Log.d(TAG, "begin preload");
bootTimingsTraceLog.traceBegin("BeginPreload");
@@ -540,10 +546,8 @@ public class ZygoteInit {
throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
} else {
- ClassLoader cl = null;
- if (systemServerClasspath != null) {
- cl = createPathClassLoader(systemServerClasspath, parsedArgs.mTargetSdkVersion);
-
+ ClassLoader cl = getOrCreateSystemServerClassLoader();
+ if (cl != null) {
Thread.currentThread().setContextClassLoader(cl);
}
@@ -559,6 +563,23 @@ public class ZygoteInit {
}
/**
+ * Create the classloader for the system server and store it in
+ * {@link sCachedSystemServerClassLoader}. This function may be called through JNI in
+ * system server startup, when the runtime is in a critically low state. Do not do
+ * extended computation etc here.
+ */
+ private static ClassLoader getOrCreateSystemServerClassLoader() {
+ if (sCachedSystemServerClassLoader == null) {
+ final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
+ if (systemServerClasspath != null) {
+ sCachedSystemServerClassLoader = createPathClassLoader(systemServerClasspath,
+ VMRuntime.SDK_VERSION_CUR_DEVELOPMENT);
+ }
+ }
+ return sCachedSystemServerClassLoader;
+ }
+
+ /**
* Note that preparing the profiles for system server does not require special selinux
* permissions. From the installer perspective the system server is a regular package which can
* capture profile information.
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 502849e4824a..90008c552995 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -122,6 +122,10 @@ static jclass gZygoteClass;
static jmethodID gCallPostForkSystemServerHooks;
static jmethodID gCallPostForkChildHooks;
+static constexpr const char* kZygoteInitClassName = "com/android/internal/os/ZygoteInit";
+static jclass gZygoteInitClass;
+static jmethodID gGetOrCreateSystemServerClassLoader;
+
static bool gIsSecurityEnforced = true;
/**
@@ -1613,6 +1617,17 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
instruction_set.value().c_str());
}
+ if (is_system_server) {
+ // Prefetch the classloader for the system server. This is done early to
+ // allow a tie-down of the proper system server selinux domain.
+ env->CallStaticVoidMethod(gZygoteInitClass, gGetOrCreateSystemServerClassLoader);
+ if (env->ExceptionCheck()) {
+ // Be robust here. The Java code will attempt to create the classloader
+ // at a later point (but may not have rights to use AoT artifacts).
+ env->ExceptionClear();
+ }
+ }
+
if (setresgid(gid, gid, gid) == -1) {
fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno)));
}
@@ -2676,6 +2691,13 @@ int register_com_android_internal_os_Zygote(JNIEnv* env) {
gCallPostForkChildHooks = GetStaticMethodIDOrDie(env, gZygoteClass, "callPostForkChildHooks",
"(IZZLjava/lang/String;)V");
- return RegisterMethodsOrDie(env, "com/android/internal/os/Zygote", gMethods, NELEM(gMethods));
+ gZygoteInitClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, kZygoteInitClassName));
+ gGetOrCreateSystemServerClassLoader =
+ GetStaticMethodIDOrDie(env, gZygoteInitClass, "getOrCreateSystemServerClassLoader",
+ "()Ljava/lang/ClassLoader;");
+
+ RegisterMethodsOrDie(env, "com/android/internal/os/Zygote", gMethods, NELEM(gMethods));
+
+ return JNI_OK;
}
} // namespace android