Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a8fe7a0 authored by Ricky Wai's avatar Ricky Wai
Browse files

Pass app visible packages data directory info to zygote

These information are needed to isolate apps data directory.

Only normal app zygote forks require these info, as
- system process - Does not need data isolation
- app zygote - It's for generating isolated process, so don't need
access apps data.
webview zygote - Similar to isolated process, don't need to access
apps data.

Bug: 143937733
Test: Able to see the package name, volume uuid, and inode nuber
for each visible package in zygote
Change-Id: I281e113d2a13d103c8967b37a06b639c5a5a8ff8
parent 10f905e1
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -22,10 +22,13 @@ import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.system.Os;
import android.system.OsConstants;
import android.util.Pair;
import android.webkit.WebViewZygote;

import dalvik.system.VMRuntime;

import java.util.Map;

/**
 * Tools for managing OS processes.
 */
@@ -521,6 +524,8 @@ public class Process {
     * @param isTopApp whether the process starts for high priority application.
     * @param disabledCompatChanges null-ok list of disabled compat changes for the process being
     *                             started.
     * @param pkgDataInfoMap Map from related package names to private data directory
     *                       volume UUID and inode number.
     * @param zygoteArgs Additional arguments to supply to the zygote process.
     * @return An object that describes the result of the attempt to start the process.
     * @throws RuntimeException on fatal start failure
@@ -541,11 +546,14 @@ public class Process {
                                           @Nullable String packageName,
                                           boolean isTopApp,
                                           @Nullable long[] disabledCompatChanges,
                                           @Nullable Map<String, Pair<String, Long>>
                                                   pkgDataInfoMap,
                                           @Nullable String[] zygoteArgs) {
        return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    /*useUsapPool=*/ true, isTopApp, disabledCompatChanges, zygoteArgs);
                    /*useUsapPool=*/ true, isTopApp, disabledCompatChanges,
                    pkgDataInfoMap, zygoteArgs);
    }

    /** @hide */
@@ -563,10 +571,13 @@ public class Process {
                                                  @Nullable String packageName,
                                                  @Nullable long[] disabledCompatChanges,
                                                  @Nullable String[] zygoteArgs) {
        // Webview zygote can't access app private data files, so doesn't need to know its data
        // info.
        return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    /*useUsapPool=*/ false, /*isTopApp=*/ false, disabledCompatChanges, zygoteArgs);
                    /*useUsapPool=*/ false, /*isTopApp=*/ false, disabledCompatChanges,
                    /* pkgDataInfoMap */ null, zygoteArgs);
    }

    /**
+33 −2
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.pm.ApplicationInfo;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
@@ -39,6 +40,7 @@ import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/*package*/ class ZygoteStartFailedEx extends Exception {
@@ -310,6 +312,8 @@ public class ZygoteProcess {
     *                             started.
     * @param zygoteArgs Additional arguments to supply to the zygote process.
     * @param isTopApp Whether the process starts for high priority application.
     * @param pkgDataInfoMap Map from related package names to private data directory
     *                       volume UUID and inode number.
     *
     * @return An object that describes the result of the attempt to start the process.
     * @throws RuntimeException on fatal start failure
@@ -328,6 +332,8 @@ public class ZygoteProcess {
                                                  boolean useUsapPool,
                                                  boolean isTopApp,
                                                  @Nullable long[] disabledCompatChanges,
                                                  @Nullable Map<String, Pair<String, Long>>
                                                          pkgDataInfoMap,
                                                  @Nullable String[] zygoteArgs) {
        // TODO (chriswailes): Is there a better place to check this value?
        if (fetchUsapPoolEnabledPropWithMinInterval()) {
@@ -338,7 +344,8 @@ public class ZygoteProcess {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
                    packageName, useUsapPool, isTopApp, disabledCompatChanges, zygoteArgs);
                    packageName, useUsapPool, isTopApp, disabledCompatChanges,
                    pkgDataInfoMap, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
@@ -539,6 +546,8 @@ public class ZygoteProcess {
     * @param packageName null-ok the name of the package this process belongs to.
     * @param isTopApp Whether the process starts for high priority application.
     * @param disabledCompatChanges a list of disabled compat changes for the process being started.
     * @param pkgDataInfoMap Map from related package names to private data directory volume UUID
     *                       and inode number.
     * @param extraArgs Additional arguments to supply to the zygote process.
     * @return An object that describes the result of the attempt to start the process.
     * @throws ZygoteStartFailedEx if process start failed for any reason
@@ -559,6 +568,8 @@ public class ZygoteProcess {
                                                      boolean useUsapPool,
                                                      boolean isTopApp,
                                                      @Nullable long[] disabledCompatChanges,
                                                      @Nullable Map<String, Pair<String, Long>>
                                                              pkgDataInfoMap,
                                                      @Nullable String[] extraArgs)
                                                      throws ZygoteStartFailedEx {
        ArrayList<String> argsForZygote = new ArrayList<>();
@@ -635,6 +646,24 @@ public class ZygoteProcess {
        if (isTopApp) {
            argsForZygote.add(Zygote.START_AS_TOP_APP_ARG);
        }
        if (pkgDataInfoMap != null && pkgDataInfoMap.size() > 0) {
            StringBuilder sb = new StringBuilder();
            sb.append(Zygote.PKG_DATA_INFO_MAP);
            sb.append("=");
            boolean started = false;
            for (Map.Entry<String, Pair<String, Long>> entry : pkgDataInfoMap.entrySet()) {
                if (started) {
                    sb.append(',');
                }
                started = true;
                sb.append(entry.getKey());
                sb.append(',');
                sb.append(entry.getValue().first);
                sb.append(',');
                sb.append(entry.getValue().second);
            }
            argsForZygote.add(sb.toString());
        }

        if (disabledCompatChanges != null && disabledCompatChanges.length > 0) {
            StringBuilder sb = new StringBuilder();
@@ -1182,12 +1211,14 @@ public class ZygoteProcess {

        Process.ProcessStartResult result;
        try {
            // As app zygote is for generating isolated process, at the end it can't access
            // apps data, so doesn't need to its data info.
            result = startViaZygote(processClass, niceName, uid, gid,
                    gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo,
                    abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
                    true /* startChildZygote */, null /* packageName */,
                    false /* useUsapPool */, false /* isTopApp */,
                    null /* disabledCompatChanges */, extraArgs);
                    null /* disabledCompatChanges */, null /* pkgDataInfoMap */, extraArgs);
        } catch (ZygoteStartFailedEx ex) {
            throw new RuntimeException("Starting child-zygote through Zygote failed", ex);
        }
+19 −7
Original line number Diff line number Diff line
@@ -151,6 +151,9 @@ public final class Zygote {
    /** Make the new process have top application priority. */
    public static final String START_AS_TOP_APP_ARG = "--is-top-app";

    /** List of packages with the same uid, and its app data info: volume uuid and inode. */
    public static final String PKG_DATA_INFO_MAP = "--pkg-data-info-map";

    /**
     * An extraArg passed when a zygote process is forking a child-zygote, specifying a name
     * in the abstract socket namespace. This socket name is what the new child zygote
@@ -254,6 +257,8 @@ public final class Zygote {
     * @param instructionSet null-ok the instruction set to use.
     * @param appDataDir null-ok the data directory of the app.
     * @param isTopApp true if the process is for top (high priority) application.
     * @param pkgDataInfoList A list that stores related packages and its app data
     * info: volume uuid and inode.
     *
     * @return 0 if this is the child, pid of the child
     * if this is the parent, or -1 on error.
@@ -261,12 +266,13 @@ public final class Zygote {
    static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
            int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
            int targetSdkVersion, boolean isTopApp) {
            int targetSdkVersion, boolean isTopApp, String[] pkgDataInfoList) {
        ZygoteHooks.preFork();

        int pid = nativeForkAndSpecialize(
                uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp);
                fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
                pkgDataInfoList);
        // Enable tracing as soon as possible for the child process.
        if (pid == 0) {
            Zygote.disableExecuteOnly(targetSdkVersion);
@@ -286,7 +292,7 @@ public final class Zygote {
    private static native int nativeForkAndSpecialize(int uid, int gid, int[] gids,
            int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
            int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
            String appDataDir, boolean isTopApp);
            String appDataDir, boolean isTopApp, String[] pkgDataInfoList);

    /**
     * Specialize an unspecialized app process.  The current VM must have been started
@@ -309,12 +315,16 @@ public final class Zygote {
     * @param instructionSet null-ok  The instruction set to use.
     * @param appDataDir null-ok  The data directory of the app.
     * @param isTopApp  True if the process is for top (high priority) application.
     * @param pkgDataInfoList A list that stores related packages and its app data
     * info: volume uuid and inode.
     */
    private static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, int mountExternal, String seInfo, String niceName,
            boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp) {
            boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
            String[] pkgDataInfoList) {
        nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
                niceName, startChildZygote, instructionSet, appDataDir, isTopApp);
                niceName, startChildZygote, instructionSet, appDataDir, isTopApp,
                pkgDataInfoList);

        // Enable tracing as soon as possible for the child process.
        Trace.setTracingEnabled(true, runtimeFlags);
@@ -336,7 +346,8 @@ public final class Zygote {

    private static native void nativeSpecializeAppProcess(int uid, int gid, int[] gids,
            int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
            boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp);
            boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
            String[] pkgDataInfoList);

    /**
     * Called to do any initialization before starting an application.
@@ -665,7 +676,8 @@ public final class Zygote {
            specializeAppProcess(args.mUid, args.mGid, args.mGids,
                                 args.mRuntimeFlags, rlimits, args.mMountExternal,
                                 args.mSeInfo, args.mNiceName, args.mStartChildZygote,
                                 args.mInstructionSet, args.mAppDataDir, args.mIsTopApp);
                                 args.mInstructionSet, args.mAppDataDir, args.mIsTopApp,
                                 args.mPkgDataInfoList);

            disableExecuteOnly(args.mTargetSdkVersion);

+8 −0
Original line number Diff line number Diff line
@@ -220,6 +220,12 @@ class ZygoteArguments {
     */
    long[] mDisabledCompatChanges = null;

    /**
     * A list that stores all related packages and its data info: volume uuid and inode.
     * Null if it does need to do app data isolation.
     */
    String[] mPkgDataInfoList;

    /**
     * Constructs instance and parses args
     *
@@ -437,6 +443,8 @@ class ZygoteArguments {
                for (int i = 0; i < length; i++) {
                    mDisabledCompatChanges[i] = Long.parseLong(params[i]);
                }
            } else if (arg.startsWith(Zygote.PKG_DATA_INFO_MAP)) {
                mPkgDataInfoList = getAssignmentList(arg);
            } else {
                break;
            }
+1 −1
Original line number Diff line number Diff line
@@ -258,7 +258,7 @@ class ZygoteConnection {
                parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
                parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
                parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion,
                parsedArgs.mIsTopApp);
                parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList);

        try {
            if (pid == 0) {
Loading