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

Commit ae017c55 authored by Kenny Root's avatar Kenny Root Committed by Android Git Automerger
Browse files

am a9543a3d: Merge "Pass additional inputs when spawning apps via the Zygote...

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

* commit 'a9543a3d':
  Pass additional inputs when spawning apps via the Zygote and add SELinux permission checks.
parents 42a6516d a9543a3d
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -359,6 +359,7 @@ public class Process {
     * @param gids Additional group-ids associated with the process.
     * @param debugFlags Additional flags.
     * @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.
     * 
     * @return An object that describes the result of the attempt to start the process.
@@ -370,10 +371,11 @@ public class Process {
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int debugFlags, int targetSdkVersion,
                                  String seInfo,
                                  String[] zygoteArgs) {
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    debugFlags, targetSdkVersion, zygoteArgs);
                    debugFlags, targetSdkVersion, seInfo, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
@@ -536,6 +538,7 @@ public class Process {
     * new process should setgroup() to.
     * @param debugFlags Additional flags.
     * @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.
     * @return An object that describes the result of the attempt to start the process.
     * @throws ZygoteStartFailedEx if process start failed for any reason
@@ -545,6 +548,7 @@ public class Process {
                                  final int uid, final int gid,
                                  final int[] gids,
                                  int debugFlags, int targetSdkVersion,
                                  String seInfo,
                                  String[] extraArgs)
                                  throws ZygoteStartFailedEx {
        synchronized(Process.class) {
@@ -595,6 +599,10 @@ public class Process {
                argsForZygote.add("--nice-name=" + niceName);
            }

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

            argsForZygote.add(processClass);

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

import android.os.SELinux;

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

    /**
     * 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);
            throw ex;
        }

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

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

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

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

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

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

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

@@ -429,6 +440,13 @@ class ZygoteConnection {
                    peerWait = true;
                } else if (arg.equals("--runtime-init")) {
                    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=")) {
                    if (capabilitiesSpecified) {
                        throw new IllegalArgumentException(
@@ -591,7 +609,8 @@ class ZygoteConnection {
     * @param peer non-null; peer credentials
     * @throws ZygoteSecurityException
     */
    private static void applyUidSecurityPolicy(Arguments args, Credentials peer)
    private static void applyUidSecurityPolicy(Arguments args, Credentials peer,
            String peerSecurityContext)
            throws ZygoteSecurityException {

        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 (!args.uidSpecified) {
            args.uid = peer.getUid();
@@ -664,7 +694,7 @@ class ZygoteConnection {
     * @throws ZygoteSecurityException
     */
    private static void applyRlimitSecurityPolicy(
            Arguments args, Credentials peer)
            Arguments args, Credentials peer, String peerSecurityContext)
            throws ZygoteSecurityException {

        int peerUid = peer.getUid();
@@ -676,6 +706,17 @@ class ZygoteConnection {
                        "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
     */
    private static void applyCapabilitiesSecurityPolicy(
            Arguments args, Credentials peer)
            Arguments args, Credentials peer, String peerSecurityContext)
            throws ZygoteSecurityException {

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

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

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

@@ -755,6 +806,52 @@ class ZygoteConnection {
            throw new ZygoteSecurityException("Peer is not permitted to specify "
                    + "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 Diff line number Diff line
@@ -2053,7 +2053,7 @@ public final class ActivityManagerService extends ActivityManagerNative
            // the PID of the new process, or else throw a RuntimeException.
            Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                    app.processName, uid, uid, gids, debugFlags,
                    app.info.targetSdkVersion, null);
                    app.info.targetSdkVersion, null, null);
            BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
            synchronized (bs) {