Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 23 additions & 12 deletions core/java/android/os/NativeZygoteProcess.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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()
Expand All @@ -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,
Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion core/java/com/android/internal/os/ZygoteExtraArgs.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
16 changes: 8 additions & 8 deletions core/jni/android_os_NativeZygoteProcess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ static std::optional<ScopedUtfChars> 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<void> payload) {
Expand All @@ -76,7 +76,7 @@ static void CreateSpawnParcel(flatbuffers::FlatBufferBuilder& builder, JNIEnv* e
std::vector<uint32_t> secondary_groups;
std::vector<RLimitData> 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<void> spawnUnion;
Expand Down Expand Up @@ -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);
Expand All @@ -158,7 +158,7 @@ static jint android_os_NativeZygoteProcess_startNativeProcess(
CreateSpawnAndroidNativeDirect(builder, packageNamePtr, startSeq, targetSdkVersion,
static_cast<unsigned>(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();
Expand All @@ -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,
Expand Down Expand Up @@ -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());

Expand Down Expand Up @@ -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",
Expand Down