diff options
| -rw-r--r-- | core/java/com/android/internal/os/ZygoteInit.java | 29 | ||||
| -rw-r--r-- | core/jni/com_android_internal_os_Zygote.cpp | 24 |
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 |