summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorMartijn Coenen <maco@google.com>2019-01-03 16:23:01 +0100
committerMartijn Coenen <maco@google.com>2019-01-18 16:37:09 +0100
commit86f08a5190c8a36497ff3b9848ce3e6d0ba2e951 (patch)
tree25eb1abc277faf7302e48f718edbd684213562a5 /core/java
parente9ffc741456af7823e958f9777ae5d8530e739b7 (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.java15
-rw-r--r--core/java/android/os/ZygoteProcess.java10
-rw-r--r--core/java/android/webkit/WebViewZygote.java4
-rw-r--r--core/java/com/android/internal/os/ChildZygoteInit.java38
-rw-r--r--core/java/com/android/internal/os/Zygote.java21
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.
*/