summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2014-11-19 10:59:01 -0800
committerDianne Hackborn <hackbod@google.com>2014-11-19 14:29:10 -0800
commitff17024e583b170312d82089fd358d278ce16c9a (patch)
tree8c88e1081fe932f64fbae35b87fad3bb6f4ddd93
parent9522055f1d10b30158b772885bf4befe06fb2a08 (diff)
downloadframeworks_base-ff17024e583b170312d82089fd358d278ce16c9a.zip
frameworks_base-ff17024e583b170312d82089fd358d278ce16c9a.tar.gz
frameworks_base-ff17024e583b170312d82089fd358d278ce16c9a.tar.bz2
Fix issue with call backs from media process.
All but a few lines of this is for issue #16013164, which allowed apps to do some operations as the media uid by having it call back to them to open a file. The problem here is with the tempory identity stuff in the activity manager, allowing us to make the open call as the original caller... ideally we should figure out a way to just get rid of all of that, but the solution here is actually easier (even though it doesn't look it) -- we now hand a token over to the openFile() call that it can use when doing permission checks to say "yes I would like the check to be against whoever is responsible for the open". This allows us to do the uid remapping for only this one specific set of permission checks, and nothing else. Also fix issue #17487348: Isolated services can access system services they shouldn't be able to. Don't send any system service IBinder objects down for the first initialization of an isolated process. Change-Id: I3c70e16e0899d7eef0bae458e83958b41ed2b75e
-rw-r--r--cmds/content/src/com/android/commands/content/Content.java2
-rw-r--r--core/java/android/app/ActivityManagerNative.java38
-rw-r--r--core/java/android/app/ContextImpl.java29
-rw-r--r--core/java/android/app/IActivityManager.java7
-rw-r--r--core/java/android/content/ContentProvider.java75
-rw-r--r--core/java/android/content/ContentProviderClient.java2
-rw-r--r--core/java/android/content/ContentProviderNative.java6
-rw-r--r--core/java/android/content/Context.java14
-rw-r--r--core/java/android/content/ContextWrapper.java13
-rw-r--r--core/java/android/content/IContentProvider.java3
-rw-r--r--core/java/android/provider/DocumentsProvider.java6
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityManagerService.java72
-rw-r--r--test-runner/src/android/test/mock/MockContentProvider.java4
-rw-r--r--test-runner/src/android/test/mock/MockContext.java13
-rw-r--r--test-runner/src/android/test/mock/MockIContentProvider.java3
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java13
17 files changed, 221 insertions, 81 deletions
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 948c9a2..bd34a9c 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -501,7 +501,7 @@ public class Content {
@Override
public void onExecute(IContentProvider provider) throws Exception {
- final ParcelFileDescriptor fd = provider.openFile(null, mUri, "r", null);
+ final ParcelFileDescriptor fd = provider.openFile(null, mUri, "r", null, null);
copy(new FileInputStream(fd.getFileDescriptor()), System.out);
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index c3028b7..6ec48e5 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1186,6 +1186,18 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case CHECK_PERMISSION_WITH_TOKEN_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ String perm = data.readString();
+ int pid = data.readInt();
+ int uid = data.readInt();
+ IBinder token = data.readStrongBinder();
+ int res = checkPermissionWithToken(perm, pid, uid, token);
+ reply.writeNoException();
+ reply.writeInt(res);
+ return true;
+ }
+
case CHECK_URI_PERMISSION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
Uri uri = Uri.CREATOR.createFromParcel(data);
@@ -1193,7 +1205,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
int uid = data.readInt();
int mode = data.readInt();
int userId = data.readInt();
- int res = checkUriPermission(uri, pid, uid, mode, userId);
+ IBinder callerToken = data.readStrongBinder();
+ int res = checkUriPermission(uri, pid, uid, mode, userId, callerToken);
reply.writeNoException();
reply.writeInt(res);
return true;
@@ -3742,7 +3755,7 @@ class ActivityManagerProxy implements IActivityManager
mRemote.transact(GET_INTENT_SENDER_TRANSACTION, data, reply, 0);
reply.readException();
IIntentSender res = IIntentSender.Stub.asInterface(
- reply.readStrongBinder());
+ reply.readStrongBinder());
data.recycle();
reply.recycle();
return res;
@@ -3851,6 +3864,22 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
return res;
}
+ public int checkPermissionWithToken(String permission, int pid, int uid, IBinder callerToken)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeString(permission);
+ data.writeInt(pid);
+ data.writeInt(uid);
+ data.writeStrongBinder(callerToken);
+ mRemote.transact(CHECK_PERMISSION_WITH_TOKEN_TRANSACTION, data, reply, 0);
+ reply.readException();
+ int res = reply.readInt();
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
public boolean clearApplicationUserData(final String packageName,
final IPackageDataObserver observer, final int userId) throws RemoteException {
Parcel data = Parcel.obtain();
@@ -3866,8 +3895,8 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
return res;
}
- public int checkUriPermission(Uri uri, int pid, int uid, int mode, int userId)
- throws RemoteException {
+ public int checkUriPermission(Uri uri, int pid, int uid, int mode, int userId,
+ IBinder callerToken) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -3876,6 +3905,7 @@ class ActivityManagerProxy implements IActivityManager
data.writeInt(uid);
data.writeInt(mode);
data.writeInt(userId);
+ data.writeStrongBinder(callerToken);
mRemote.transact(CHECK_URI_PERMISSION_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 7fafc38..1de9b47 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1863,6 +1863,21 @@ class ContextImpl extends Context {
}
}
+ /** @hide */
+ @Override
+ public int checkPermission(String permission, int pid, int uid, IBinder callerToken) {
+ if (permission == null) {
+ throw new IllegalArgumentException("permission is null");
+ }
+
+ try {
+ return ActivityManagerNative.getDefault().checkPermissionWithToken(
+ permission, pid, uid, callerToken);
+ } catch (RemoteException e) {
+ return PackageManager.PERMISSION_DENIED;
+ }
+ }
+
@Override
public int checkCallingPermission(String permission) {
if (permission == null) {
@@ -1951,7 +1966,19 @@ class ContextImpl extends Context {
try {
return ActivityManagerNative.getDefault().checkUriPermission(
ContentProvider.getUriWithoutUserId(uri), pid, uid, modeFlags,
- resolveUserId(uri));
+ resolveUserId(uri), null);
+ } catch (RemoteException e) {
+ return PackageManager.PERMISSION_DENIED;
+ }
+ }
+
+ /** @hide */
+ @Override
+ public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags, IBinder callerToken) {
+ try {
+ return ActivityManagerNative.getDefault().checkUriPermission(
+ ContentProvider.getUriWithoutUserId(uri), pid, uid, modeFlags,
+ resolveUserId(uri), callerToken);
} catch (RemoteException e) {
return PackageManager.PERMISSION_DENIED;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 6433f3f..5362303 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -219,9 +219,11 @@ public interface IActivityManager extends IInterface {
public int checkPermission(String permission, int pid, int uid)
throws RemoteException;
-
- public int checkUriPermission(Uri uri, int pid, int uid, int mode, int userId)
+ public int checkPermissionWithToken(String permission, int pid, int uid, IBinder callerToken)
throws RemoteException;
+
+ public int checkUriPermission(Uri uri, int pid, int uid, int mode, int userId,
+ IBinder callerToken) throws RemoteException;
public void grantUriPermission(IApplicationThread caller, String targetPkg, Uri uri,
int mode, int userId) throws RemoteException;
public void revokeUriPermission(IApplicationThread caller, Uri uri, int mode, int userId)
@@ -785,4 +787,5 @@ public interface IActivityManager extends IInterface {
int GET_TASK_DESCRIPTION_ICON_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+238;
int LAUNCH_ASSIST_INTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+239;
int START_IN_PLACE_ANIMATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+240;
+ int CHECK_PERMISSION_WITH_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+241;
}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 4c82efd..360f308 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -31,6 +31,7 @@ import android.os.AsyncTask;
import android.os.Binder;
import android.os.Bundle;
import android.os.CancellationSignal;
+import android.os.IBinder;
import android.os.ICancellationSignal;
import android.os.OperationCanceledException;
import android.os.ParcelFileDescriptor;
@@ -201,7 +202,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
ICancellationSignal cancellationSignal) {
validateIncomingUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
return rejectQuery(uri, projection, selection, selectionArgs, sortOrder,
CancellationSignal.fromTransport(cancellationSignal));
}
@@ -227,7 +228,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
return rejectInsert(uri, initialValues);
}
final String original = setCallingPackage(callingPkg);
@@ -242,7 +243,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
public int bulkInsert(String callingPkg, Uri uri, ContentValues[] initialValues) {
validateIncomingUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
return 0;
}
final String original = setCallingPackage(callingPkg);
@@ -270,13 +271,13 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
operations.set(i, operation);
}
if (operation.isReadOperation()) {
- if (enforceReadPermission(callingPkg, uri)
+ if (enforceReadPermission(callingPkg, uri, null)
!= AppOpsManager.MODE_ALLOWED) {
throw new OperationApplicationException("App op not allowed", 0);
}
}
if (operation.isWriteOperation()) {
- if (enforceWritePermission(callingPkg, uri)
+ if (enforceWritePermission(callingPkg, uri, null)
!= AppOpsManager.MODE_ALLOWED) {
throw new OperationApplicationException("App op not allowed", 0);
}
@@ -301,7 +302,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) {
validateIncomingUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
return 0;
}
final String original = setCallingPackage(callingPkg);
@@ -317,7 +318,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
String[] selectionArgs) {
validateIncomingUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
return 0;
}
final String original = setCallingPackage(callingPkg);
@@ -330,11 +331,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override
public ParcelFileDescriptor openFile(
- String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
- throws FileNotFoundException {
+ String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal,
+ IBinder callerToken) throws FileNotFoundException {
validateIncomingUri(uri);
uri = getUriWithoutUserId(uri);
- enforceFilePermission(callingPkg, uri, mode);
+ enforceFilePermission(callingPkg, uri, mode, callerToken);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.openFile(
@@ -350,7 +351,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
throws FileNotFoundException {
validateIncomingUri(uri);
uri = getUriWithoutUserId(uri);
- enforceFilePermission(callingPkg, uri, mode);
+ enforceFilePermission(callingPkg, uri, mode, null);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.openAssetFile(
@@ -382,7 +383,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
validateIncomingUri(uri);
uri = getUriWithoutUserId(uri);
- enforceFilePermission(callingPkg, uri, "r");
+ enforceFilePermission(callingPkg, uri, "r", null);
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.openTypedAssetFile(
@@ -402,7 +403,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
return null;
}
final String original = setCallingPackage(callingPkg);
@@ -418,7 +419,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
return null;
}
final String original = setCallingPackage(callingPkg);
@@ -429,29 +430,33 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
}
}
- private void enforceFilePermission(String callingPkg, Uri uri, String mode)
- throws FileNotFoundException, SecurityException {
+ private void enforceFilePermission(String callingPkg, Uri uri, String mode,
+ IBinder callerToken) throws FileNotFoundException, SecurityException {
if (mode != null && mode.indexOf('w') != -1) {
- if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceWritePermission(callingPkg, uri, callerToken)
+ != AppOpsManager.MODE_ALLOWED) {
throw new FileNotFoundException("App op not allowed");
}
} else {
- if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceReadPermission(callingPkg, uri, callerToken)
+ != AppOpsManager.MODE_ALLOWED) {
throw new FileNotFoundException("App op not allowed");
}
}
}
- private int enforceReadPermission(String callingPkg, Uri uri) throws SecurityException {
- enforceReadPermissionInner(uri);
+ private int enforceReadPermission(String callingPkg, Uri uri, IBinder callerToken)
+ throws SecurityException {
+ enforceReadPermissionInner(uri, callerToken);
if (mReadOp != AppOpsManager.OP_NONE) {
return mAppOpsManager.noteOp(mReadOp, Binder.getCallingUid(), callingPkg);
}
return AppOpsManager.MODE_ALLOWED;
}
- private int enforceWritePermission(String callingPkg, Uri uri) throws SecurityException {
- enforceWritePermissionInner(uri);
+ private int enforceWritePermission(String callingPkg, Uri uri, IBinder callerToken)
+ throws SecurityException {
+ enforceWritePermissionInner(uri, callerToken);
if (mWriteOp != AppOpsManager.OP_NONE) {
return mAppOpsManager.noteOp(mWriteOp, Binder.getCallingUid(), callingPkg);
}
@@ -467,7 +472,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
}
/** {@hide} */
- protected void enforceReadPermissionInner(Uri uri) throws SecurityException {
+ protected void enforceReadPermissionInner(Uri uri, IBinder callerToken)
+ throws SecurityException {
final Context context = getContext();
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
@@ -480,7 +486,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (mExported && checkUser(pid, uid, context)) {
final String componentPerm = getReadPermission();
if (componentPerm != null) {
- if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) {
+ if (context.checkPermission(componentPerm, pid, uid, callerToken)
+ == PERMISSION_GRANTED) {
return;
} else {
missingPerm = componentPerm;
@@ -497,7 +504,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
for (PathPermission pp : pps) {
final String pathPerm = pp.getReadPermission();
if (pathPerm != null && pp.match(path)) {
- if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) {
+ if (context.checkPermission(pathPerm, pid, uid, callerToken)
+ == PERMISSION_GRANTED) {
return;
} else {
// any denied <path-permission> means we lose
@@ -518,8 +526,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
final int callingUserId = UserHandle.getUserId(uid);
final Uri userUri = (mSingleUser && !UserHandle.isSameUser(mMyUid, uid))
? maybeAddUserId(uri, callingUserId) : uri;
- if (context.checkUriPermission(userUri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
- == PERMISSION_GRANTED) {
+ if (context.checkUriPermission(userUri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ callerToken) == PERMISSION_GRANTED) {
return;
}
@@ -532,7 +540,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
}
/** {@hide} */
- protected void enforceWritePermissionInner(Uri uri) throws SecurityException {
+ protected void enforceWritePermissionInner(Uri uri, IBinder callerToken)
+ throws SecurityException {
final Context context = getContext();
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
@@ -545,7 +554,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (mExported && checkUser(pid, uid, context)) {
final String componentPerm = getWritePermission();
if (componentPerm != null) {
- if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) {
+ if (context.checkPermission(componentPerm, pid, uid, callerToken)
+ == PERMISSION_GRANTED) {
return;
} else {
missingPerm = componentPerm;
@@ -562,7 +572,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
for (PathPermission pp : pps) {
final String pathPerm = pp.getWritePermission();
if (pathPerm != null && pp.match(path)) {
- if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) {
+ if (context.checkPermission(pathPerm, pid, uid, callerToken)
+ == PERMISSION_GRANTED) {
return;
} else {
// any denied <path-permission> means we lose
@@ -580,8 +591,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
}
// last chance, check against any uri grants
- if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
- == PERMISSION_GRANTED) {
+ if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
+ callerToken) == PERMISSION_GRANTED) {
return;
}
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index cefc27f..e15ac94 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -288,7 +288,7 @@ public class ContentProviderClient {
remoteSignal = mContentProvider.createCancellationSignal();
signal.setRemote(remoteSignal);
}
- return mContentProvider.openFile(mPackageName, url, mode, remoteSignal);
+ return mContentProvider.openFile(mPackageName, url, mode, remoteSignal, null);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index 39286d6..f2e7fc4 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -234,9 +234,10 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
String mode = data.readString();
ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
data.readStrongBinder());
+ IBinder callerToken = data.readStrongBinder();
ParcelFileDescriptor fd;
- fd = openFile(callingPkg, url, mode, signal);
+ fd = openFile(callingPkg, url, mode, signal, callerToken);
reply.writeNoException();
if (fd != null) {
reply.writeInt(1);
@@ -575,7 +576,7 @@ final class ContentProviderProxy implements IContentProvider
@Override
public ParcelFileDescriptor openFile(
- String callingPkg, Uri url, String mode, ICancellationSignal signal)
+ String callingPkg, Uri url, String mode, ICancellationSignal signal, IBinder token)
throws RemoteException, FileNotFoundException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -586,6 +587,7 @@ final class ContentProviderProxy implements IContentProvider
url.writeToParcel(data, 0);
data.writeString(mode);
data.writeStrongBinder(signal != null ? signal.asBinder() : null);
+ data.writeStrongBinder(token);
mRemote.transact(IContentProvider.OPEN_FILE_TRANSACTION, data, reply, 0);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c9b7d0a..a73ba74 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -37,6 +37,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.StatFs;
import android.os.UserHandle;
@@ -2864,10 +2865,10 @@ public abstract class Context {
/**
* Use with {@link #getSystemService} to retrieve a {@link
- * android.app.UsageStatsManager} for interacting with the status bar.
+ * android.app.usage.UsageStatsManager} for interacting with the status bar.
*
* @see #getSystemService
- * @see android.app.UsageStatsManager
+ * @see android.app.usage.UsageStatsManager
* @hide
*/
public static final String USAGE_STATS_SERVICE = "usagestats";
@@ -2921,6 +2922,11 @@ public abstract class Context {
@PackageManager.PermissionResult
public abstract int checkPermission(@NonNull String permission, int pid, int uid);
+ /** @hide */
+ @PackageManager.PermissionResult
+ public abstract int checkPermission(@NonNull String permission, int pid, int uid,
+ IBinder callerToken);
+
/**
* Determine whether the calling process of an IPC you are handling has been
* granted a particular permission. This is basically the same as calling
@@ -3108,6 +3114,10 @@ public abstract class Context {
public abstract int checkUriPermission(Uri uri, int pid, int uid,
@Intent.AccessUriMode int modeFlags);
+ /** @hide */
+ public abstract int checkUriPermission(Uri uri, int pid, int uid,
+ @Intent.AccessUriMode int modeFlags, IBinder callerToken);
+
/**
* Determine whether the calling process and user ID has been
* granted permission to access a specific URI. This is basically
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index ad7c350..cfae1cf 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -29,6 +29,7 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.UserHandle;
import android.view.DisplayAdjustments;
@@ -566,6 +567,12 @@ public class ContextWrapper extends Context {
return mBase.checkPermission(permission, pid, uid);
}
+ /** @hide */
+ @Override
+ public int checkPermission(String permission, int pid, int uid, IBinder callerToken) {
+ return mBase.checkPermission(permission, pid, uid, callerToken);
+ }
+
@Override
public int checkCallingPermission(String permission) {
return mBase.checkCallingPermission(permission);
@@ -608,6 +615,12 @@ public class ContextWrapper extends Context {
return mBase.checkUriPermission(uri, pid, uid, modeFlags);
}
+ /** @hide */
+ @Override
+ public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags, IBinder callerToken) {
+ return mBase.checkUriPermission(uri, pid, uid, modeFlags, callerToken);
+ }
+
@Override
public int checkCallingUriPermission(Uri uri, int modeFlags) {
return mBase.checkCallingUriPermission(uri, modeFlags);
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index f92a404..f858406 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -47,7 +47,8 @@ public interface IContentProvider extends IInterface {
public int update(String callingPkg, Uri url, ContentValues values, String selection,
String[] selectionArgs) throws RemoteException;
public ParcelFileDescriptor openFile(
- String callingPkg, Uri url, String mode, ICancellationSignal signal)
+ String callingPkg, Uri url, String mode, ICancellationSignal signal,
+ IBinder callerToken)
throws RemoteException, FileNotFoundException;
public AssetFileDescriptor openAssetFile(
String callingPkg, Uri url, String mode, ICancellationSignal signal)
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 270d786..4135e8b 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -637,7 +637,7 @@ public abstract class DocumentsProvider extends ContentProvider {
final Bundle out = new Bundle();
try {
if (METHOD_CREATE_DOCUMENT.equals(method)) {
- enforceWritePermissionInner(documentUri);
+ enforceWritePermissionInner(documentUri, null);
final String mimeType = extras.getString(Document.COLUMN_MIME_TYPE);
final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
@@ -651,7 +651,7 @@ public abstract class DocumentsProvider extends ContentProvider {
out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri);
} else if (METHOD_RENAME_DOCUMENT.equals(method)) {
- enforceWritePermissionInner(documentUri);
+ enforceWritePermissionInner(documentUri, null);
final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
final String newDocumentId = renameDocument(documentId, displayName);
@@ -675,7 +675,7 @@ public abstract class DocumentsProvider extends ContentProvider {
}
} else if (METHOD_DELETE_DOCUMENT.equals(method)) {
- enforceWritePermissionInner(documentUri);
+ enforceWritePermissionInner(documentUri, null);
deleteDocument(documentId);
// Document no longer exists, clean up any grants
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 772192a..8001757 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -834,10 +834,12 @@ public final class ActivityManagerService extends ActivityManagerNative
* indirect content-provider access.
*/
private class Identity {
- public int pid;
- public int uid;
+ public final IBinder token;
+ public final int pid;
+ public final int uid;
- Identity(int _pid, int _uid) {
+ Identity(IBinder _token, int _pid, int _uid) {
+ token = _token;
pid = _pid;
uid = _uid;
}
@@ -2271,15 +2273,19 @@ public final class ActivityManagerService extends ActivityManagerNative
* process when the bindApplication() IPC is sent to the process. They're
* lazily setup to make sure the services are running when they're asked for.
*/
- private HashMap<String, IBinder> getCommonServicesLocked() {
+ private HashMap<String, IBinder> getCommonServicesLocked(boolean isolated) {
if (mAppBindArgs == null) {
- mAppBindArgs = new HashMap<String, IBinder>();
+ mAppBindArgs = new HashMap<>();
- // Setup the application init args
- mAppBindArgs.put("package", ServiceManager.getService("package"));
- mAppBindArgs.put("window", ServiceManager.getService("window"));
- mAppBindArgs.put(Context.ALARM_SERVICE,
- ServiceManager.getService(Context.ALARM_SERVICE));
+ // Isolated processes won't get this optimization, so that we don't
+ // violate the rules about which services they have access to.
+ if (!isolated) {
+ // Setup the application init args
+ mAppBindArgs.put("package", ServiceManager.getService("package"));
+ mAppBindArgs.put("window", ServiceManager.getService("window"));
+ mAppBindArgs.put(Context.ALARM_SERVICE,
+ ServiceManager.getService(Context.ALARM_SERVICE));
+ }
}
return mAppBindArgs;
}
@@ -5902,7 +5908,8 @@ public final class ActivityManagerService extends ActivityManagerNative
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
isRestrictedBackupMode || !normalMode, app.persistent,
- new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
+ new Configuration(mConfiguration), app.compat,
+ getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, null);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
@@ -6722,21 +6729,9 @@ public final class ActivityManagerService extends ActivityManagerNative
*/
int checkComponentPermission(String permission, int pid, int uid,
int owningUid, boolean exported) {
- // We might be performing an operation on behalf of an indirect binder
- // invocation, e.g. via {@link #openContentUri}. Check and adjust the
- // client identity accordingly before proceeding.
- Identity tlsIdentity = sCallerIdentity.get();
- if (tlsIdentity != null) {
- Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
- + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
- uid = tlsIdentity.uid;
- pid = tlsIdentity.pid;
- }
-
if (pid == MY_PID) {
return PackageManager.PERMISSION_GRANTED;
}
-
return ActivityManager.checkComponentPermission(permission, uid,
owningUid, exported);
}
@@ -6758,6 +6753,26 @@ public final class ActivityManagerService extends ActivityManagerNative
return checkComponentPermission(permission, pid, UserHandle.getAppId(uid), -1, true);
}
+ @Override
+ public int checkPermissionWithToken(String permission, int pid, int uid, IBinder callerToken) {
+ if (permission == null) {
+ return PackageManager.PERMISSION_DENIED;
+ }
+
+ // We might be performing an operation on behalf of an indirect binder
+ // invocation, e.g. via {@link #openContentUri}. Check and adjust the
+ // client identity accordingly before proceeding.
+ Identity tlsIdentity = sCallerIdentity.get();
+ if (tlsIdentity != null && tlsIdentity.token == callerToken) {
+ Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
+ + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
+ uid = tlsIdentity.uid;
+ pid = tlsIdentity.pid;
+ }
+
+ return checkComponentPermission(permission, pid, UserHandle.getAppId(uid), -1, true);
+ }
+
/**
* Binder IPC calls go through the public entry point.
* This can be called with or without the global lock held.
@@ -6963,13 +6978,13 @@ public final class ActivityManagerService extends ActivityManagerNative
*/
@Override
public int checkUriPermission(Uri uri, int pid, int uid,
- final int modeFlags, int userId) {
+ final int modeFlags, int userId, IBinder callerToken) {
enforceNotIsolatedCaller("checkUriPermission");
// Another redirected-binder-call permissions check as in
- // {@link checkComponentPermission}.
+ // {@link checkPermissionWithToken}.
Identity tlsIdentity = sCallerIdentity.get();
- if (tlsIdentity != null) {
+ if (tlsIdentity != null && tlsIdentity.token == callerToken) {
uid = tlsIdentity.uid;
pid = tlsIdentity.pid;
}
@@ -9876,10 +9891,11 @@ public final class ActivityManagerService extends ActivityManagerNative
// we do the check against the caller's permissions even though it looks
// to the content provider like the Activity Manager itself is making
// the request.
+ Binder token = new Binder();
sCallerIdentity.set(new Identity(
- Binder.getCallingPid(), Binder.getCallingUid()));
+ token, Binder.getCallingPid(), Binder.getCallingUid()));
try {
- pfd = cph.provider.openFile(null, uri, "r", null);
+ pfd = cph.provider.openFile(null, uri, "r", null, token);
} catch (FileNotFoundException e) {
// do nothing; pfd will be returned null
} finally {
diff --git a/test-runner/src/android/test/mock/MockContentProvider.java b/test-runner/src/android/test/mock/MockContentProvider.java
index 28d52b0..5ef71df 100644
--- a/test-runner/src/android/test/mock/MockContentProvider.java
+++ b/test-runner/src/android/test/mock/MockContentProvider.java
@@ -91,8 +91,8 @@ public class MockContentProvider extends ContentProvider {
@Override
public ParcelFileDescriptor openFile(
- String callingPackage, Uri url, String mode, ICancellationSignal signal)
- throws RemoteException, FileNotFoundException {
+ String callingPackage, Uri url, String mode, ICancellationSignal signal,
+ IBinder callerToken) throws RemoteException, FileNotFoundException {
return MockContentProvider.this.openFile(url, mode);
}
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 46c81b6..3378872 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -37,6 +37,7 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.UserHandle;
import android.view.DisplayAdjustments;
@@ -483,6 +484,12 @@ public class MockContext extends Context {
throw new UnsupportedOperationException();
}
+ /** @hide */
+ @Override
+ public int checkPermission(String permission, int pid, int uid, IBinder callerToken) {
+ return checkPermission(permission, pid, uid);
+ }
+
@Override
public int checkCallingPermission(String permission) {
throw new UnsupportedOperationException();
@@ -524,6 +531,12 @@ public class MockContext extends Context {
throw new UnsupportedOperationException();
}
+ /** @hide */
+ @Override
+ public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags, IBinder callerToken) {
+ return checkUriPermission(uri, pid, uid, modeFlags);
+ }
+
@Override
public int checkCallingUriPermission(Uri uri, int modeFlags) {
throw new UnsupportedOperationException();
diff --git a/test-runner/src/android/test/mock/MockIContentProvider.java b/test-runner/src/android/test/mock/MockIContentProvider.java
index c0dc7c3..ee8c376 100644
--- a/test-runner/src/android/test/mock/MockIContentProvider.java
+++ b/test-runner/src/android/test/mock/MockIContentProvider.java
@@ -62,7 +62,8 @@ public class MockIContentProvider implements IContentProvider {
}
public ParcelFileDescriptor openFile(
- String callingPackage, Uri url, String mode, ICancellationSignal signal) {
+ String callingPackage, Uri url, String mode, ICancellationSignal signal,
+ IBinder callerToken) {
throw new UnsupportedOperationException("unimplemented mock method");
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
index 89288bf..e4cbb2f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
@@ -90,7 +90,7 @@ public final class BridgeContentProvider implements IContentProvider {
@Override
public ParcelFileDescriptor openFile(
- String callingPackage, Uri arg0, String arg1, ICancellationSignal signal)
+ String callingPackage, Uri arg0, String arg1, ICancellationSignal signal, IBinder token)
throws RemoteException, FileNotFoundException {
// TODO Auto-generated method stub
return null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index aeb70e9..2c3736f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -16,6 +16,7 @@
package com.android.layoutlib.bridge.android;
+import android.os.IBinder;
import com.android.annotations.Nullable;
import com.android.ide.common.rendering.api.ILayoutPullParser;
import com.android.ide.common.rendering.api.IProjectCallback;
@@ -938,12 +939,24 @@ public final class BridgeContext extends Context {
}
@Override
+ public int checkPermission(String arg0, int arg1, int arg2, IBinder arg3) {
+ // pass
+ return 0;
+ }
+
+ @Override
public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) {
// pass
return 0;
}
@Override
+ public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4) {
+ // pass
+ return 0;
+ }
+
+ @Override
public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3,
int arg4, int arg5) {
// pass