Add new feature for running services in "isolated" sandbox processes.
This reserves a range of uids (for each user) in which these processes
run. These uids are not associated with an application, so they
effectively run with no permissions. When a Service requests to
run in such a process through android:isolatedProcess="true", each
time it is brought up a new isolated process is started with its
own unique uid.
What we have so far gives us the basic infrastructure; more work
remains to further lock down what these uids have access to.
Change-Id: Ibfd27c75619cba61f528f46ede9113f98dc5f45b
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e4cfc99..bf632a9 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -134,7 +134,7 @@
private static final boolean DEBUG_RESULTS = false;
private static final boolean DEBUG_BACKUP = true;
private static final boolean DEBUG_CONFIGURATION = false;
- private static final boolean DEBUG_SERVICE = true;
+ private static final boolean DEBUG_SERVICE = false;
private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";");
private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
@@ -3764,13 +3764,17 @@
}
private void setupGraphicsSupport(LoadedApk info) {
+ if (Process.isIsolated()) {
+ // Isolated processes aren't going to do UI.
+ return;
+ }
try {
int uid = Process.myUid();
String[] packages = getPackageManager().getPackagesForUid(uid);
// If there are several packages in this application we won't
// initialize the graphics disk caches
- if (packages.length == 1) {
+ if (packages != null && packages.length == 1) {
ContextImpl appContext = new ContextImpl();
appContext.init(info, null, this);
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index fcbcd81..d9bbb4a 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -119,7 +119,7 @@
final int myUid = Process.myUid();
mResDir = aInfo.uid == myUid ? aInfo.sourceDir
: aInfo.publicSourceDir;
- if (!UserId.isSameUser(aInfo.uid, myUid)) {
+ if (!UserId.isSameUser(aInfo.uid, myUid) && !Process.isIsolated()) {
aInfo.dataDir = PackageManager.getDataDirForUser(UserId.getUserId(myUid),
mPackageName);
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index faee873..2023f82 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2581,6 +2581,11 @@
false)) {
s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
}
+ if (sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
+ false)) {
+ s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
+ }
sa.recycle();
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index 612e345..7ee84ab 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -42,10 +42,17 @@
public static final int FLAG_STOP_WITH_TASK = 0x0001;
/**
+ * Bit in {@link #flags}: If set, the service will run in its own
+ * isolated process. Set from the
+ * {@link android.R.attr#isolatedProcess} attribute.
+ */
+ public static final int FLAG_ISOLATED_PROCESS = 0x0002;
+
+ /**
* Options that have been set in the service declaration in the
* manifest.
* These include:
- * {@link #FLAG_STOP_WITH_TASK}
+ * {@link #FLAG_STOP_WITH_TASK}, {@link #FLAG_ISOLATED_PROCESS}.
*/
public int flags;
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index cdf235d..0746af8 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -119,7 +119,19 @@
* Last of application-specific UIDs starting at
* {@link #FIRST_APPLICATION_UID}.
*/
- public static final int LAST_APPLICATION_UID = 99999;
+ public static final int LAST_APPLICATION_UID = 89999;
+
+ /**
+ * First uid used for fully isolated sandboxed processes (with no permissions of their own)
+ * @hide
+ */
+ public static final int FIRST_ISOLATED_UID = 99000;
+
+ /**
+ * Last uid used for fully isolated sandboxed processes (with no permissions of their own)
+ * @hide
+ */
+ public static final int LAST_ISOLATED_UID = 99999;
/**
* Defines a secondary group id for access to the bluetooth hardware.
@@ -576,6 +588,15 @@
public static final native int myUid();
/**
+ * Returns whether the current process is in an isolated sandbox.
+ * @hide
+ */
+ public static final boolean isIsolated() {
+ int uid = UserId.getAppId(myUid());
+ return uid >= FIRST_ISOLATED_UID && uid <= LAST_ISOLATED_UID;
+ }
+
+ /**
* Returns the UID assigned to a particular user name, or -1 if there is
* none. If the given string consists of only numbers, it is converted
* directly to a uid.
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index dbd49fb..92c59ab 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1235,6 +1235,10 @@
when the user remove a task rooted in an activity owned by
the application. The default is false. -->
<attr name="stopWithTask" format="boolean" />
+ <!-- If set to true, this service will run under a special process
+ that is isolated from the rest of the system. The only communication
+ with it is through the Service API (binding and starting). -->
+ <attr name="isolatedProcess" format="boolean" />
</declare-styleable>
<!-- The <code>receiver</code> tag declares an
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e3c2bd8..1b91643 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3482,4 +3482,10 @@
<public type="color" name="holo_orange_dark" id="0x01060019" />
<public type="color" name="holo_purple" id="0x0106001a" />
<public type="color" name="holo_blue_bright" id="0x0106001b" />
+
+<!-- ===============================================================
+ Resources added in version 16 of the platform (Jelly Bean)
+ =============================================================== -->
+ <public type="attr" name="isolatedProcess" id="0x010103a7" />
+
</resources>