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

Commit a9543a3d authored by Kenny Root's avatar Kenny Root Committed by android code review
Browse files

Merge "Pass additional inputs when spawning apps via the Zygote and add SELinux permission checks."

parents 20d6caf8 83d9eda9
Loading
Loading
Loading
Loading
+9 −1
Original line number Original line Diff line number Diff line
@@ -274,6 +274,7 @@ public class Process {
     * @param gids Additional group-ids associated with the process.
     * @param gids Additional group-ids associated with the process.
     * @param debugFlags Additional flags.
     * @param debugFlags Additional flags.
     * @param targetSdkVersion The target SDK version for the app.
     * @param targetSdkVersion The target SDK version for the app.
     * @param seInfo null-ok SE Android information for the new process.
     * @param zygoteArgs Additional arguments to supply to the zygote process.
     * @param zygoteArgs Additional arguments to supply to the zygote process.
     * 
     * 
     * @return An object that describes the result of the attempt to start the process.
     * @return An object that describes the result of the attempt to start the process.
@@ -285,10 +286,11 @@ public class Process {
                                  final String niceName,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int uid, int gid, int[] gids,
                                  int debugFlags, int targetSdkVersion,
                                  int debugFlags, int targetSdkVersion,
                                  String seInfo,
                                  String[] zygoteArgs) {
                                  String[] zygoteArgs) {
        try {
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    debugFlags, targetSdkVersion, zygoteArgs);
                    debugFlags, targetSdkVersion, seInfo, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
                    "Starting VM process through Zygote failed");
@@ -451,6 +453,7 @@ public class Process {
     * new process should setgroup() to.
     * new process should setgroup() to.
     * @param debugFlags Additional flags.
     * @param debugFlags Additional flags.
     * @param targetSdkVersion The target SDK version for the app.
     * @param targetSdkVersion The target SDK version for the app.
     * @param seInfo null-ok SE Android information for the new process.
     * @param extraArgs Additional arguments to supply to the zygote process.
     * @param extraArgs Additional arguments to supply to the zygote process.
     * @return An object that describes the result of the attempt to start the process.
     * @return An object that describes the result of the attempt to start the process.
     * @throws ZygoteStartFailedEx if process start failed for any reason
     * @throws ZygoteStartFailedEx if process start failed for any reason
@@ -460,6 +463,7 @@ public class Process {
                                  final int uid, final int gid,
                                  final int uid, final int gid,
                                  final int[] gids,
                                  final int[] gids,
                                  int debugFlags, int targetSdkVersion,
                                  int debugFlags, int targetSdkVersion,
                                  String seInfo,
                                  String[] extraArgs)
                                  String[] extraArgs)
                                  throws ZygoteStartFailedEx {
                                  throws ZygoteStartFailedEx {
        synchronized(Process.class) {
        synchronized(Process.class) {
@@ -510,6 +514,10 @@ public class Process {
                argsForZygote.add("--nice-name=" + niceName);
                argsForZygote.add("--nice-name=" + niceName);
            }
            }


            if (seInfo != null) {
                argsForZygote.add("--seinfo=" + seInfo);
            }

            argsForZygote.add(processClass);
            argsForZygote.add(processClass);


            if (extraArgs != null) {
            if (extraArgs != null) {
+106 −9
Original line number Original line Diff line number Diff line
@@ -26,6 +26,8 @@ import android.util.Log;
import dalvik.system.PathClassLoader;
import dalvik.system.PathClassLoader;
import dalvik.system.Zygote;
import dalvik.system.Zygote;


import android.os.SELinux;

import java.io.BufferedReader;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataOutputStream;
@@ -73,6 +75,7 @@ class ZygoteConnection {
    private final DataOutputStream mSocketOutStream;
    private final DataOutputStream mSocketOutStream;
    private final BufferedReader mSocketReader;
    private final BufferedReader mSocketReader;
    private final Credentials peer;
    private final Credentials peer;
    private final String peerSecurityContext;


    /**
    /**
     * A long-lived reference to the original command socket used to launch
     * A long-lived reference to the original command socket used to launch
@@ -109,6 +112,8 @@ class ZygoteConnection {
            Log.e(TAG, "Cannot read peer credentials", ex);
            Log.e(TAG, "Cannot read peer credentials", ex);
            throw ex;
            throw ex;
        }
        }

        peerSecurityContext = SELinux.getPeerContext(mSocket.getFileDescriptor());
    }
    }


    /**
    /**
@@ -207,10 +212,11 @@ class ZygoteConnection {
        try {
        try {
            parsedArgs = new Arguments(args);
            parsedArgs = new Arguments(args);


            applyUidSecurityPolicy(parsedArgs, peer);
            applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext);
            applyRlimitSecurityPolicy(parsedArgs, peer);
            applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext);
            applyCapabilitiesSecurityPolicy(parsedArgs, peer);
            applyCapabilitiesSecurityPolicy(parsedArgs, peer, peerSecurityContext);
            applyInvokeWithSecurityPolicy(parsedArgs, peer);
            applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext);
            applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext);


            applyDebuggerSystemProperty(parsedArgs);
            applyDebuggerSystemProperty(parsedArgs);
            applyInvokeWithSystemProperty(parsedArgs);
            applyInvokeWithSystemProperty(parsedArgs);
@@ -229,7 +235,8 @@ class ZygoteConnection {
            }
            }


            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids, parsedArgs.debugFlags, rlimits);
                    parsedArgs.gids, parsedArgs.debugFlags, rlimits,
                    parsedArgs.seInfo, parsedArgs.niceName);
        } catch (IOException ex) {
        } catch (IOException ex) {
            logAndPrintError(newStderr, "Exception creating pipe", ex);
            logAndPrintError(newStderr, "Exception creating pipe", ex);
        } catch (ErrnoException ex) {
        } catch (ErrnoException ex) {
@@ -352,6 +359,10 @@ class ZygoteConnection {
        long permittedCapabilities;
        long permittedCapabilities;
        long effectiveCapabilities;
        long effectiveCapabilities;


        /** from --seinfo */
        boolean seInfoSpecified;
        String seInfo;

        /** from all --rlimit=r,c,m */
        /** from all --rlimit=r,c,m */
        ArrayList<int[]> rlimits;
        ArrayList<int[]> rlimits;


@@ -429,6 +440,13 @@ class ZygoteConnection {
                    peerWait = true;
                    peerWait = true;
                } else if (arg.equals("--runtime-init")) {
                } else if (arg.equals("--runtime-init")) {
                    runtimeInit = true;
                    runtimeInit = true;
                } else if (arg.startsWith("--seinfo=")) {
                    if (seInfoSpecified) {
                        throw new IllegalArgumentException(
                                "Duplicate arg specified");
                    }
                    seInfoSpecified = true;
                    seInfo = arg.substring(arg.indexOf('=') + 1);
                } else if (arg.startsWith("--capabilities=")) {
                } else if (arg.startsWith("--capabilities=")) {
                    if (capabilitiesSpecified) {
                    if (capabilitiesSpecified) {
                        throw new IllegalArgumentException(
                        throw new IllegalArgumentException(
@@ -591,7 +609,8 @@ class ZygoteConnection {
     * @param peer non-null; peer credentials
     * @param peer non-null; peer credentials
     * @throws ZygoteSecurityException
     * @throws ZygoteSecurityException
     */
     */
    private static void applyUidSecurityPolicy(Arguments args, Credentials peer)
    private static void applyUidSecurityPolicy(Arguments args, Credentials peer,
            String peerSecurityContext)
            throws ZygoteSecurityException {
            throws ZygoteSecurityException {


        int peerUid = peer.getUid();
        int peerUid = peer.getUid();
@@ -624,6 +643,17 @@ class ZygoteConnection {
            }
            }
        }
        }


        if (args.uidSpecified || args.gidSpecified || args.gids != null) {
            boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext,
                                                         peerSecurityContext,
                                                         "zygote",
                                                         "specifyids");
            if (!allowed) {
                throw new ZygoteSecurityException(
                        "Peer may not specify uid's or gid's");
            }
        }

        // If not otherwise specified, uid and gid are inherited from peer
        // If not otherwise specified, uid and gid are inherited from peer
        if (!args.uidSpecified) {
        if (!args.uidSpecified) {
            args.uid = peer.getUid();
            args.uid = peer.getUid();
@@ -664,7 +694,7 @@ class ZygoteConnection {
     * @throws ZygoteSecurityException
     * @throws ZygoteSecurityException
     */
     */
    private static void applyRlimitSecurityPolicy(
    private static void applyRlimitSecurityPolicy(
            Arguments args, Credentials peer)
            Arguments args, Credentials peer, String peerSecurityContext)
            throws ZygoteSecurityException {
            throws ZygoteSecurityException {


        int peerUid = peer.getUid();
        int peerUid = peer.getUid();
@@ -676,6 +706,17 @@ class ZygoteConnection {
                        "This UID may not specify rlimits.");
                        "This UID may not specify rlimits.");
            }
            }
        }
        }

        if (args.rlimits != null) {
            boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext,
                                                         peerSecurityContext,
                                                         "zygote",
                                                         "specifyrlimits");
            if (!allowed) {
                throw new ZygoteSecurityException(
                        "Peer may not specify rlimits");
            }
         }
    }
    }


    /**
    /**
@@ -689,7 +730,7 @@ class ZygoteConnection {
     * @throws ZygoteSecurityException
     * @throws ZygoteSecurityException
     */
     */
    private static void applyCapabilitiesSecurityPolicy(
    private static void applyCapabilitiesSecurityPolicy(
            Arguments args, Credentials peer)
            Arguments args, Credentials peer, String peerSecurityContext)
            throws ZygoteSecurityException {
            throws ZygoteSecurityException {


        if (args.permittedCapabilities == 0
        if (args.permittedCapabilities == 0
@@ -698,6 +739,15 @@ class ZygoteConnection {
            return;
            return;
        }
        }


        boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext,
                                                     peerSecurityContext,
                                                     "zygote",
                                                     "specifycapabilities");
        if (!allowed) {
            throw new ZygoteSecurityException(
                    "Peer may not specify capabilities");
        }

        if (peer.getUid() == 0) {
        if (peer.getUid() == 0) {
            // root may specify anything
            // root may specify anything
            return;
            return;
@@ -747,7 +797,8 @@ class ZygoteConnection {
     * @param peer non-null; peer credentials
     * @param peer non-null; peer credentials
     * @throws ZygoteSecurityException
     * @throws ZygoteSecurityException
     */
     */
    private static void applyInvokeWithSecurityPolicy(Arguments args, Credentials peer)
    private static void applyInvokeWithSecurityPolicy(Arguments args, Credentials peer,
            String peerSecurityContext)
            throws ZygoteSecurityException {
            throws ZygoteSecurityException {
        int peerUid = peer.getUid();
        int peerUid = peer.getUid();


@@ -755,6 +806,52 @@ class ZygoteConnection {
            throw new ZygoteSecurityException("Peer is not permitted to specify "
            throw new ZygoteSecurityException("Peer is not permitted to specify "
                    + "an explicit invoke-with wrapper command");
                    + "an explicit invoke-with wrapper command");
        }
        }

        if (args.invokeWith != null) {
            boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext,
                                                         peerSecurityContext,
                                                         "zygote",
                                                         "specifyinvokewith");
            if (!allowed) {
                throw new ZygoteSecurityException("Peer is not permitted to specify "
                    + "an explicit invoke-with wrapper command");
            }
        }
    }

    /**
     * Applies zygote security policy for SEAndroid information.
     *
     * @param args non-null; zygote spawner arguments
     * @param peer non-null; peer credentials
     * @throws ZygoteSecurityException
     */
    private static void applyseInfoSecurityPolicy(
            Arguments args, Credentials peer, String peerSecurityContext)
            throws ZygoteSecurityException {
        int peerUid = peer.getUid();

        if (args.seInfo == null) {
            // nothing to check
            return;
        }

        if (!(peerUid == 0 || peerUid == Process.SYSTEM_UID)) {
            // All peers with UID other than root or SYSTEM_UID
            throw new ZygoteSecurityException(
                    "This UID may not specify SEAndroid info.");
        }

        boolean allowed = SELinux.checkSELinuxAccess(peerSecurityContext,
                                                     peerSecurityContext,
                                                     "zygote",
                                                     "specifyseinfo");
        if (!allowed) {
            throw new ZygoteSecurityException(
                    "Peer may not specify SEAndroid info");
        }

        return;
    }
    }


    /**
    /**
+1 −1
Original line number Original line Diff line number Diff line
@@ -1967,7 +1967,7 @@ public final class ActivityManagerService extends ActivityManagerNative
            // the PID of the new process, or else throw a RuntimeException.
            // the PID of the new process, or else throw a RuntimeException.
            Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
            Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                    app.processName, uid, uid, gids, debugFlags,
                    app.processName, uid, uid, gids, debugFlags,
                    app.info.targetSdkVersion, null);
                    app.info.targetSdkVersion, null, null);
            BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
            BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
            synchronized (bs) {
            synchronized (bs) {