diff --git a/core/java/android/os/NativeZygoteProcess.java b/core/java/android/os/NativeZygoteProcess.java index 6a2beb1313738..bf457ba5b7741 100644 --- a/core/java/android/os/NativeZygoteProcess.java +++ b/core/java/android/os/NativeZygoteProcess.java @@ -26,6 +26,7 @@ import android.util.Pair; import com.android.internal.os.Zygote; +import com.android.internal.os.ZygoteExtraArgs; import java.io.FileDescriptor; import java.io.IOException; @@ -80,19 +81,28 @@ private synchronized void connectToZygote() throws IOException { } } - private static native int nativeStartNativeProcess( + private static native int nativeStartNativeProcess(long selinuxFlags, FileDescriptor fd, int uid, int gid, long startSeq, String packageName, String niceName, int targetSdkVersion, boolean startChildZygote, int runtimeFlags, String seInfo, boolean isTopApp) throws IOException; - private static native int nativeStartNativeChildZygote( + private static native int nativeStartNativeChildZygote(long selinuxFlags, FileDescriptor parentFd, int uid, int gid, String niceName, String seInfo, int targetSdkVersion, int runtimeFlags, String serverAddress, int uidRangeStart, int uidRangeEnd, String allowedLibPath, String librarySearchPaths, boolean isShared, String zipPath, String nativeSharedLibPath, String libraryPath, String preloadFunc) throws IOException; + private static long getSelinuxFlags(@Nullable String flatExtraArgs) { + if (flatExtraArgs != null) { + String value = flatExtraArgs.substring(flatExtraArgs.indexOf('=') + 1); + var extraArgs = ZygoteExtraArgs.parse(value); + return extraArgs.selinuxFlags; + } + return 0L; + } + @Override public final Process.ProcessStartResult start(@NonNull final String processClass, final String niceName, @@ -120,12 +130,17 @@ public final Process.ProcessStartResult start(@NonNull final String processClass long startSeq, @Nullable String[] zygoteArgs, @Nullable String flatExtraArgs) { - checkFlagExtraArgs(flatExtraArgs); + // there are currently 3 custom runtime flags: + // - DISABLE_HARDENED_MALLOC and ENABLE_COMPAT_VA_39_BIT require exec spawning which is not + // currently supported for native zygote + // - FORCIBLY_ENABLE_MEMORY_TAGGING is low-impact and isn't needed in practice since native + // zygote is mainly used by Chromium browsers which opt-in to memory tagging + runtimeFlags &= ~Zygote.CUSTOM_RUNTIME_FLAGS; int pid; try { connectToZygote(); - pid = nativeStartNativeProcess(mSocket.getFileDescriptor(), uid, gid, startSeq, + pid = nativeStartNativeProcess(getSelinuxFlags(flatExtraArgs), mSocket.getFileDescriptor(), uid, gid, startSeq, packageName, niceName, targetSdkVersion, /*startChildZygote=*/false, runtimeFlags, seInfo, isTopApp); if (pid == -1) { @@ -153,7 +168,9 @@ public ChildZygoteProcess startChildZygote(final String processClass, int uidRangeEnd, ApplicationInfo appInfo, @Nullable String flatExtraArgs) { - checkFlagExtraArgs(flatExtraArgs); + // see comment in start() above + runtimeFlags &= ~Zygote.CUSTOM_RUNTIME_FLAGS; + // Create an unguessable address in the global abstract namespace. String serverAddress = processClass + "/" + UUID.randomUUID().toString(); // The address of abstract socket should be prefixed with '@'. LocalSocket.connect() @@ -174,7 +191,7 @@ public ChildZygoteProcess startChildZygote(final String processClass, int pid; try { connectToZygote(); - pid = nativeStartNativeChildZygote(mSocket.getFileDescriptor(), uid, gid, niceName, + pid = nativeStartNativeChildZygote(getSelinuxFlags(flatExtraArgs), mSocket.getFileDescriptor(), uid, gid, niceName, seInfo, appInfo.targetSdkVersion, runtimeFlags, serverAddressForNative, uidRangeStart, uidRangeEnd, params.permittedLibsDir, params.libPath, params.isShared, params.zipPath, params.nativeSharedLibs, @@ -199,12 +216,6 @@ public boolean preloadApp(ApplicationInfo appInfo, String abi) { return false; } - private static void checkFlagExtraArgs(@Nullable String flatExtraArgs) { - if (flatExtraArgs != null && !flatExtraArgs.equals("--flat-extra-args=0")) { - throw new IllegalStateException("flatExtraArgs passed to NativeZygoteProcess: " + flatExtraArgs); - } - } - @Override public void close() { if (mSocket != null) { diff --git a/core/java/com/android/internal/os/ZygoteExtraArgs.java b/core/java/com/android/internal/os/ZygoteExtraArgs.java index 755c44841115c..5790a1dcabe4e 100644 --- a/core/java/com/android/internal/os/ZygoteExtraArgs.java +++ b/core/java/com/android/internal/os/ZygoteExtraArgs.java @@ -45,7 +45,7 @@ public static String createFlatForWebviewProcess(Context ctx, int userId, return PREFIX + String.join(SEPARATOR, arr); } - static ZygoteExtraArgs parse(String flat) { + public static ZygoteExtraArgs parse(String flat) { String[] arr = flat.split(SEPARATOR); long selinuxFlags = Long.parseLong(arr[IDX_SELINUX_FLAGS], 16); return new ZygoteExtraArgs(selinuxFlags); diff --git a/core/jni/android_os_NativeZygoteProcess.cpp b/core/jni/android_os_NativeZygoteProcess.cpp index c90dd0133b340..71e352d6367d0 100644 --- a/core/jni/android_os_NativeZygoteProcess.cpp +++ b/core/jni/android_os_NativeZygoteProcess.cpp @@ -58,7 +58,7 @@ static std::optional extract_jstring(JNIEnv* env, jstring manage return ScopedUtfChars(env, managed_string); } -static void CreateSpawnParcel(flatbuffers::FlatBufferBuilder& builder, JNIEnv* env, jint uid, +static void CreateSpawnParcel(flatbuffers::FlatBufferBuilder& builder, JNIEnv* env, jlong selinux_flags, jint uid, jint gid, const char* niceNameStr, bool is_child_zygote, const char* seInfoStr, const char* socketPathStr, SpawnPayload payload_type, flatbuffers::Offset payload) { @@ -76,7 +76,7 @@ static void CreateSpawnParcel(flatbuffers::FlatBufferBuilder& builder, JNIEnv* e std::vector secondary_groups; std::vector rlimits; auto spawnCommon = - CreateSpawnCommonDirect(builder, uid, gid, niceNameStr, priority_initial, + CreateSpawnCommonDirect(builder, selinux_flags, uid, gid, niceNameStr, priority_initial, priority_final, cap_effective, cap_permitted, cap_inheritable, cap_bound, seInfoStr, &secondary_groups, &rlimits); flatbuffers::Offset spawnUnion; @@ -137,7 +137,7 @@ bool waitUntilNativeZygoteReady() { namespace android { static jint android_os_NativeZygoteProcess_startNativeProcess( - JNIEnv* env, jclass /* classObj */, jobject sockFd, jint uid, jint gid, jlong startSeq, + JNIEnv* env, jclass /* classObj */, jlong selinuxFlags, jobject sockFd, jint uid, jint gid, jlong startSeq, jstring packageName, jstring niceName, jint targetSdkVersion, jboolean startChildZygote, jint runtimeFlags, jstring seInfo, jboolean isTopApp) { int fd = jniGetFDFromFileDescriptor(env, sockFd); @@ -158,7 +158,7 @@ static jint android_os_NativeZygoteProcess_startNativeProcess( CreateSpawnAndroidNativeDirect(builder, packageNamePtr, startSeq, targetSdkVersion, static_cast(runtimeFlags), is_top_app); bool is_child_zygote = startChildZygote == JNI_TRUE; - CreateSpawnParcel(builder, env, uid, gid, niceNamePtr, is_child_zygote, seInfoPtr, + CreateSpawnParcel(builder, env, selinuxFlags, uid, gid, niceNamePtr, is_child_zygote, seInfoPtr, /**subspecies_data=*/nullptr, SpawnPayload_SpawnAndroidNative, spawnAndroidNativeCmd.Union()); uint8_t* buf = builder.GetBufferPointer(); @@ -174,7 +174,7 @@ static jint android_os_NativeZygoteProcess_startNativeProcess( } static jint android_os_NativeZygoteProcess_startNativeChildZygote( - JNIEnv* env, jclass /* classObj */, jobject sockFd, jint uid, jint gid, jstring niceName, + JNIEnv* env, jclass /* classObj */, jlong selinuxFlags, jobject sockFd, jint uid, jint gid, jstring niceName, jstring seInfo, jint targetSdkVersion, jint runtimeFlags, jstring serverPath, jint uidRangeStart, jint uidRangeEnd, jstring allowedLibPath, jstring librarySearchPaths, jboolean isShared, jstring zipPath, jstring nativeSharedLibPath, jstring libraryPath, @@ -215,7 +215,7 @@ static jint android_os_NativeZygoteProcess_startNativeChildZygote( zipPathStr, nativeSharedLibPathStr, preloadFuncStr, uidRangeStart, uidRangeEnd); - CreateSpawnParcel(builder, env, uid, gid, niceNameStr, /**is_child_zygote=*/true, seInfoStr, + CreateSpawnParcel(builder, env, selinuxFlags, uid, gid, niceNameStr, /**is_child_zygote=*/true, seInfoStr, serverPathStr, SpawnPayload_SpawnSubspeciesAndroidNative, spawnAndroidChildZygoteCmd.Union()); @@ -261,10 +261,10 @@ static void android_os_NativeZygoteProcess_prewarmNativeZygote(JNIEnv* env, jcla static const JNINativeMethod method_table[] = { /* name, signature, funcPtr */ {"nativeStartNativeProcess", - "(Ljava/io/FileDescriptor;IIJLjava/lang/String;Ljava/lang/String;IZILjava/lang/String;Z)I", + "(JLjava/io/FileDescriptor;IIJLjava/lang/String;Ljava/lang/String;IZILjava/lang/String;Z)I", (void*)android_os_NativeZygoteProcess_startNativeProcess}, {"nativeStartNativeChildZygote", - "(Ljava/io/FileDescriptor;IILjava/lang/String;Ljava/lang/String;II" + "(JLjava/io/FileDescriptor;IILjava/lang/String;Ljava/lang/String;II" "Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/" "String;Ljava/lang/String;" "Ljava/lang/String;)I",