diff options
| author | Martijn Coenen <maco@google.com> | 2019-01-03 16:23:01 +0100 |
|---|---|---|
| committer | Martijn Coenen <maco@google.com> | 2019-01-18 16:37:09 +0100 |
| commit | 86f08a5190c8a36497ff3b9848ce3e6d0ba2e951 (patch) | |
| tree | 25eb1abc277faf7302e48f718edbd684213562a5 /core/java | |
| parent | e9ffc741456af7823e958f9777ae5d8530e739b7 (diff) | |
Prepare setresuid()/setresgid() seccomp filter in AppZygote.
The application zygote can run untrusted user code; since it also
has the capability to change the uid/gid of the process, we need
to ensure that any changes to the uid and/or gid stay within the
range that we have allocated for this application zygote.
For application zygotes, we install the app_zygote seccomp
filter instead of the regular app filter; the only difference
between this filter and the app one is that it allows
setuid/setgid calls.
To further limit this, pass down the allocated UID range to the
Zygote itself, which in turn installs an additional seccomp
filter that restricts setuid/setgid calls to this range.
The actual calls into seccomp are commented out until the seccomp
changes are merged; to avoid catastrophe, this will leave the
regular app filter for the app_zygote, which is more restrictive
and doesn't allow setuid at all.
Bug: 111434506
Test: atest CtsSeccompHostTestCases passes
Change-Id: I112419629f5ee4774ccbf77e2b1cfa5ddcf77e73
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/os/AppZygote.java | 15 | ||||
| -rw-r--r-- | core/java/android/os/ZygoteProcess.java | 10 | ||||
| -rw-r--r-- | core/java/android/webkit/WebViewZygote.java | 4 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/ChildZygoteInit.java | 38 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/Zygote.java | 21 |
5 files changed, 83 insertions, 5 deletions
diff --git a/core/java/android/os/AppZygote.java b/core/java/android/os/AppZygote.java index 40cbaf75c02d..950f38167754 100644 --- a/core/java/android/os/AppZygote.java +++ b/core/java/android/os/AppZygote.java @@ -34,8 +34,15 @@ import com.android.internal.annotations.GuardedBy; public class AppZygote { private static final String LOG_TAG = "AppZygote"; + // UID of the Zygote itself private final int mZygoteUid; + // First UID/GID of the range the AppZygote can setuid()/setgid() to + private final int mZygoteUidGidMin; + + // Last UID/GID of the range the AppZygote can setuid()/setgid() to + private final int mZygoteUidGidMax; + private final Object mLock = new Object(); /** @@ -47,9 +54,11 @@ public class AppZygote { private final ApplicationInfo mAppInfo; - public AppZygote(ApplicationInfo appInfo, int zygoteUid) { + public AppZygote(ApplicationInfo appInfo, int zygoteUid, int uidGidMin, int uidGidMax) { mAppInfo = appInfo; mZygoteUid = zygoteUid; + mZygoteUidGidMin = uidGidMin; + mZygoteUidGidMax = uidGidMax; } /** @@ -104,7 +113,9 @@ public class AppZygote { "app_zygote", // seInfo abi, // abi abi, // acceptedAbiList - null); // instructionSet + null, // instructionSet + mZygoteUidGidMin, + mZygoteUidGidMax); ZygoteProcess.waitForConnectionToZygote(mZygote.getPrimarySocketAddress()); // preload application code in the zygote diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java index 251c5eebadc4..99a85eaefe53 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -809,6 +809,8 @@ public class ZygoteProcess { * may be different from <code>abi</code> in case the children * spawned from this Zygote only communicate using ABI-safe methods. * @param instructionSet null-ok the instruction set to use. + * @param uidRangeStart The first UID in the range the child zygote may setuid()/setgid() to + * @param uidRangeEnd The last UID in the range the child zygote may setuid()/setgid() to */ public ChildZygoteProcess startChildZygote(final String processClass, final String niceName, @@ -817,13 +819,17 @@ public class ZygoteProcess { String seInfo, String abi, String acceptedAbiList, - String instructionSet) { + String instructionSet, + int uidRangeStart, + int uidRangeEnd) { // Create an unguessable address in the global abstract namespace. final LocalSocketAddress serverAddress = new LocalSocketAddress( processClass + "/" + UUID.randomUUID().toString()); final String[] extraArgs = {Zygote.CHILD_ZYGOTE_SOCKET_NAME_ARG + serverAddress.getName(), - Zygote.CHILD_ZYGOTE_ABI_LIST_ARG + acceptedAbiList}; + Zygote.CHILD_ZYGOTE_ABI_LIST_ARG + acceptedAbiList, + Zygote.CHILD_ZYGOTE_UID_RANGE_START + uidRangeStart, + Zygote.CHILD_ZYGOTE_UID_RANGE_END + uidRangeEnd}; Process.ProcessStartResult result; try { diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java index 9f7aa6a2852a..29b3b3cff044 100644 --- a/core/java/android/webkit/WebViewZygote.java +++ b/core/java/android/webkit/WebViewZygote.java @@ -160,7 +160,9 @@ public class WebViewZygote { "webview_zygote", // seInfo sPackage.applicationInfo.primaryCpuAbi, // abi TextUtils.join(",", Build.SUPPORTED_ABIS), - null); // instructionSet + null, // instructionSet + Process.FIRST_ISOLATED_UID, + Process.LAST_ISOLATED_UID); // All the work below is usually done by LoadedApk, but the zygote can't talk to // PackageManager or construct a LoadedApk since it's single-threaded pre-fork, so diff --git a/core/java/com/android/internal/os/ChildZygoteInit.java b/core/java/com/android/internal/os/ChildZygoteInit.java index f90cd0224596..a052a3b3ab6a 100644 --- a/core/java/com/android/internal/os/ChildZygoteInit.java +++ b/core/java/com/android/internal/os/ChildZygoteInit.java @@ -15,6 +15,7 @@ */ package com.android.internal.os; +import android.os.Process; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; @@ -49,6 +50,22 @@ public class ChildZygoteInit { return null; } + static int parseIntFromArg(String[] argv, String desiredArg) { + int value = -1; + for (String arg : argv) { + if (arg.startsWith(desiredArg)) { + String valueStr = arg.substring(arg.indexOf('=') + 1); + try { + value = Integer.parseInt(valueStr); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid int argument: " + + valueStr, e); + } + } + } + return value; + } + /** * Starts a ZygoteServer and listens for requests * @@ -72,6 +89,27 @@ public class ChildZygoteInit { throw new RuntimeException("Failed to set PR_SET_NO_NEW_PRIVS", ex); } + int uidGidMin = parseIntFromArg(args, Zygote.CHILD_ZYGOTE_UID_RANGE_START); + int uidGidMax = parseIntFromArg(args, Zygote.CHILD_ZYGOTE_UID_RANGE_END); + if (uidGidMin == -1 || uidGidMax == -1) { + throw new RuntimeException("Couldn't parse UID range start/end"); + } + if (uidGidMin > uidGidMax) { + throw new RuntimeException("Passed in UID range is invalid, min > max."); + } + + // Verify the UIDs are in the isolated UID range, as that's the only thing that we should + // be forking right now + if (!Process.isIsolated(uidGidMin) || !Process.isIsolated(uidGidMax)) { + throw new RuntimeException("Passed in UID range does not map to isolated processes."); + } + + /** + * Install a seccomp filter that ensure this Zygote can only setuid()/setgid() + * to the passed in range. + */ + Zygote.nativeInstallSeccompUidGidFilter(uidGidMin, uidGidMax); + final Runnable caller; try { server.registerServerSocketAtAbstractName(socketName); diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index d720c689f5de..f5746ca65f5e 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -104,6 +104,20 @@ public final class Zygote { */ public static final String CHILD_ZYGOTE_ABI_LIST_ARG = "--abi-list="; + /** + * An extraArg passed when a zygote process is forking a child-zygote, specifying the + * start of the UID range the children of the Zygote may setuid()/setgid() to. This + * will be enforced with a seccomp filter. + */ + public static final String CHILD_ZYGOTE_UID_RANGE_START = "--uid-range-start="; + + /** + * An extraArg passed when a zygote process is forking a child-zygote, specifying the + * end of the UID range the children of the Zygote may setuid()/setgid() to. This + * will be enforced with a seccomp filter. + */ + public static final String CHILD_ZYGOTE_UID_RANGE_END = "--uid-range-end="; + private Zygote() {} /** Called for some security initialization before any fork. */ @@ -222,6 +236,13 @@ public final class Zygote { native protected static void nativeAllowFileAcrossFork(String path); /** + * Installs a seccomp filter that limits setresuid()/setresgid() to the passed-in range + * @param uidGidMin The smallest allowed uid/gid + * @param uidGidMax The largest allowed uid/gid + */ + native protected static void nativeInstallSeccompUidGidFilter(int uidGidMin, int uidGidMax); + + /** * Zygote unmount storage space on initializing. * This method is called once. */ |
