diff options
Diffstat (limited to 'core/java/android')
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 20 | ||||
-rw-r--r-- | core/java/android/app/AppOpsManager.java | 97 | ||||
-rw-r--r-- | core/java/android/app/ContextImpl.java | 10 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 11 | ||||
-rw-r--r-- | core/java/android/content/BroadcastReceiver.java | 2 | ||||
-rw-r--r-- | core/java/android/content/ContentProvider.java | 24 |
6 files changed, 140 insertions, 24 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 2bb4e76..cc93ac9 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -921,8 +921,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM IApplicationThread app = ApplicationThreadNative.asInterface(b); Intent service = Intent.CREATOR.createFromParcel(data); String resolvedType = data.readString(); + String callingPackage = data.readString(); int userId = data.readInt(); - ComponentName cn = startService(app, service, resolvedType, userId); + ComponentName cn = startService(app, service, resolvedType, callingPackage, userId); reply.writeNoException(); ComponentName.writeToParcel(cn, reply); return true; @@ -976,9 +977,11 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM String resolvedType = data.readString(); b = data.readStrongBinder(); int fl = data.readInt(); + String callingPackage = data.readString(); int userId = data.readInt(); IServiceConnection conn = IServiceConnection.Stub.asInterface(b); - int res = bindService(app, token, service, resolvedType, conn, fl, userId); + int res = bindService(app, token, service, resolvedType, conn, fl, + callingPackage, userId); reply.writeNoException(); reply.writeInt(res); return true; @@ -1568,7 +1571,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM data.enforceInterface(IActivityManager.descriptor); Intent service = Intent.CREATOR.createFromParcel(data); String resolvedType = data.readString(); - IBinder binder = peekService(service, resolvedType); + String callingPackage = data.readString(); + IBinder binder = peekService(service, resolvedType, callingPackage); reply.writeNoException(); reply.writeStrongBinder(binder); return true; @@ -3638,7 +3642,7 @@ class ActivityManagerProxy implements IActivityManager } public ComponentName startService(IApplicationThread caller, Intent service, - String resolvedType, int userId) throws RemoteException + String resolvedType, String callingPackage, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -3646,6 +3650,7 @@ class ActivityManagerProxy implements IActivityManager data.writeStrongBinder(caller != null ? caller.asBinder() : null); service.writeToParcel(data, 0); data.writeString(resolvedType); + data.writeString(callingPackage); data.writeInt(userId); mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0); reply.readException(); @@ -3708,7 +3713,7 @@ class ActivityManagerProxy implements IActivityManager } public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, - int flags, int userId) throws RemoteException { + int flags, String callingPackage, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -3718,6 +3723,7 @@ class ActivityManagerProxy implements IActivityManager data.writeString(resolvedType); data.writeStrongBinder(connection.asBinder()); data.writeInt(flags); + data.writeString(callingPackage); data.writeInt(userId); mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0); reply.readException(); @@ -3783,12 +3789,14 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } - public IBinder peekService(Intent service, String resolvedType) throws RemoteException { + public IBinder peekService(Intent service, String resolvedType, String callingPackage) + throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); service.writeToParcel(data, 0); data.writeString(resolvedType); + data.writeString(callingPackage); mRemote.transact(PEEK_SERVICE_TRANSACTION, data, reply, 0); reply.readException(); IBinder binder = reply.readStrongBinder(); diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 9faadd3..bf3bfae 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -1082,13 +1082,18 @@ public class AppOpsManager { private final long mTime; private final long mRejectTime; private final int mDuration; + private final int mProxyUid; + private final String mProxyPackageName; - public OpEntry(int op, int mode, long time, long rejectTime, int duration) { + public OpEntry(int op, int mode, long time, long rejectTime, int duration, + int proxyUid, String proxyPackage) { mOp = op; mMode = mode; mTime = time; mRejectTime = rejectTime; mDuration = duration; + mProxyUid = proxyUid; + mProxyPackageName = proxyPackage; } public int getOp() { @@ -1115,6 +1120,14 @@ public class AppOpsManager { return mDuration == -1 ? (int)(System.currentTimeMillis()-mTime) : mDuration; } + public int getProxyUid() { + return mProxyUid; + } + + public String getProxyPackageName() { + return mProxyPackageName; + } + @Override public int describeContents() { return 0; @@ -1127,6 +1140,8 @@ public class AppOpsManager { dest.writeLong(mTime); dest.writeLong(mRejectTime); dest.writeInt(mDuration); + dest.writeInt(mProxyUid); + dest.writeString(mProxyPackageName); } OpEntry(Parcel source) { @@ -1135,6 +1150,8 @@ public class AppOpsManager { mTime = source.readLong(); mRejectTime = source.readLong(); mDuration = source.readInt(); + mProxyUid = source.readInt(); + mProxyPackageName = source.readString(); } public static final Creator<OpEntry> CREATOR = new Creator<OpEntry>() { @@ -1379,6 +1396,33 @@ public class AppOpsManager { } /** + * Make note of an application performing an operation on behalf of another + * application when handling an IPC. Note that you must pass the package name + * of the application that is being proxied while its UID will be inferred from + * the IPC state; this function will verify that the calling uid and proxied + * package name match, and if not, return {@link #MODE_IGNORED}. If this call + * succeeds, the last execution time of the operation for the proxied app and + * your app will be updated to the current time. + * @param op The operation to note. One of the OPSTR_* constants. + * @param proxiedPackageName The name of the application calling into the proxy application. + * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or + * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without + * causing the app to crash). + * @throws SecurityException If the app has been configured to crash on this op. + */ + public int noteProxyOp(String op, String proxiedPackageName) { + return noteProxyOp(strOpToOp(op), proxiedPackageName); + } + + /** + * Like {@link #noteProxyOp(String, String)} but instead + * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}. + */ + public int noteProxyOpNoThrow(String op, String proxiedPackageName) { + return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName); + } + + /** * Report that an application has started executing a long-running operation. Note that you * must pass in both the uid and name of the application to be checked; this function will * verify that these two match, and if not, return {@link #MODE_IGNORED}. If this call @@ -1455,7 +1499,7 @@ public class AppOpsManager { return mService.checkOperation(op, uid, packageName); } catch (RemoteException e) { } - return MODE_IGNORED; + return MODE_ERRORED; } /** @@ -1501,7 +1545,7 @@ public class AppOpsManager { return mService.checkAudioOperation(op, stream, uid, packageName); } catch (RemoteException e) { } - return MODE_IGNORED; + return MODE_ERRORED; } /** @@ -1532,6 +1576,49 @@ public class AppOpsManager { } /** + * Make note of an application performing an operation on behalf of another + * application when handling an IPC. Note that you must pass the package name + * of the application that is being proxied while its UID will be inferred from + * the IPC state; this function will verify that the calling uid and proxied + * package name match, and if not, return {@link #MODE_IGNORED}. If this call + * succeeds, the last execution time of the operation for the proxied app and + * your app will be updated to the current time. + * @param op The operation to note. One of the OPSTR_* constants. + * @param proxiedPackageName The name of the application calling into the proxy application. + * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or + * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without + * causing the app to crash). + * @throws SecurityException If the proxy or proxied app has been configured to + * crash on this op. + * + * @hide + */ + public int noteProxyOp(int op, String proxiedPackageName) { + int mode = noteProxyOpNoThrow(op, proxiedPackageName); + if (mode == MODE_ERRORED) { + throw new SecurityException("Proxy package " + mContext.getOpPackageName() + + " from uid " + Process.myUid() + " or calling package " + + proxiedPackageName + " from uid " + Binder.getCallingUid() + + " not allowed to perform " + sOpNames[op]); + } + return mode; + } + + /** + * Like {@link #noteProxyOp(int, String)} but instead + * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}. + * @hide + */ + public int noteProxyOpNoThrow(int op, String proxiedPackageName) { + try { + return mService.noteProxyOperation(op, mContext.getOpPackageName(), + Binder.getCallingUid(), proxiedPackageName); + } catch (RemoteException e) { + } + return MODE_ERRORED; + } + + /** * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it * returns {@link #MODE_ERRORED}. * @hide @@ -1541,7 +1628,7 @@ public class AppOpsManager { return mService.noteOperation(op, uid, packageName); } catch (RemoteException e) { } - return MODE_IGNORED; + return MODE_ERRORED; } /** @hide */ @@ -1603,7 +1690,7 @@ public class AppOpsManager { return mService.startOperation(getToken(mService), op, uid, packageName); } catch (RemoteException e) { } - return MODE_IGNORED; + return MODE_ERRORED; } /** @hide */ diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 0420fb6..6639486 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1202,8 +1202,8 @@ class ContextImpl extends Context { validateServiceIntent(service); service.prepareToLeaveProcess(); ComponentName cn = ActivityManagerNative.getDefault().startService( - mMainThread.getApplicationThread(), service, - service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier()); + mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( + getContentResolver()), getOpPackageName(), user.getIdentifier()); if (cn != null) { if (cn.getPackageName().equals("!")) { throw new SecurityException( @@ -1279,9 +1279,9 @@ class ContextImpl extends Context { } service.prepareToLeaveProcess(); int res = ActivityManagerNative.getDefault().bindService( - mMainThread.getApplicationThread(), getActivityToken(), - service, service.resolveTypeIfNeeded(getContentResolver()), - sd, flags, user.getIdentifier()); + mMainThread.getApplicationThread(), getActivityToken(), service, + service.resolveTypeIfNeeded(getContentResolver()), + sd, flags, getOpPackageName(), user.getIdentifier()); if (res < 0) { throw new SecurityException( "Not allowed to bind to service " + service); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 1423e4b..acce81c 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -160,16 +160,16 @@ public interface IActivityManager extends IInterface { public PendingIntent getRunningServiceControlPanel(ComponentName service) throws RemoteException; public ComponentName startService(IApplicationThread caller, Intent service, - String resolvedType, int userId) throws RemoteException; + String resolvedType, String callingPackage, int userId) throws RemoteException; public int stopService(IApplicationThread caller, Intent service, String resolvedType, int userId) throws RemoteException; public boolean stopServiceToken(ComponentName className, IBinder token, int startId) throws RemoteException; public void setServiceForeground(ComponentName className, IBinder token, int id, Notification notification, boolean keepNotification) throws RemoteException; - public int bindService(IApplicationThread caller, IBinder token, - Intent service, String resolvedType, - IServiceConnection connection, int flags, int userId) throws RemoteException; + public int bindService(IApplicationThread caller, IBinder token, Intent service, + String resolvedType, IServiceConnection connection, int flags, + String callingPackage, int userId) throws RemoteException; public boolean unbindService(IServiceConnection connection) throws RemoteException; public void publishService(IBinder token, Intent intent, IBinder service) throws RemoteException; @@ -178,7 +178,8 @@ public interface IActivityManager extends IInterface { /* oneway */ public void serviceDoneExecuting(IBinder token, int type, int startId, int res) throws RemoteException; - public IBinder peekService(Intent service, String resolvedType) throws RemoteException; + public IBinder peekService(Intent service, String resolvedType, String callingPackage) + throws RemoteException; public boolean bindBackupAgent(ApplicationInfo appInfo, int backupRestoreMode) throws RemoteException; diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java index af74e73..2260d7e 100644 --- a/core/java/android/content/BroadcastReceiver.java +++ b/core/java/android/content/BroadcastReceiver.java @@ -524,7 +524,7 @@ public abstract class BroadcastReceiver { try { service.prepareToLeaveProcess(); binder = am.peekService(service, service.resolveTypeIfNeeded( - myContext.getContentResolver())); + myContext.getContentResolver()), myContext.getOpPackageName()); } catch (RemoteException e) { } return binder; diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index d4c4437..3cc7684 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -475,18 +475,38 @@ public abstract class ContentProvider implements ComponentCallbacks2 { private int enforceReadPermission(String callingPkg, Uri uri, IBinder callerToken) throws SecurityException { enforceReadPermissionInner(uri, callerToken); + + final int permOp = AppOpsManager.permissionToOpCode(mReadPermission); + if (permOp != AppOpsManager.OP_NONE) { + final int mode = mAppOpsManager.noteProxyOp(permOp, callingPkg); + if (mode != AppOpsManager.MODE_ALLOWED) { + return mode; + } + } + if (mReadOp != AppOpsManager.OP_NONE) { - return mAppOpsManager.noteOp(mReadOp, Binder.getCallingUid(), callingPkg); + return mAppOpsManager.noteProxyOp(mReadOp, callingPkg); } + return AppOpsManager.MODE_ALLOWED; } private int enforceWritePermission(String callingPkg, Uri uri, IBinder callerToken) throws SecurityException { enforceWritePermissionInner(uri, callerToken); + + final int permOp = AppOpsManager.permissionToOpCode(mWritePermission); + if (permOp != AppOpsManager.OP_NONE) { + final int mode = mAppOpsManager.noteProxyOp(permOp, callingPkg); + if (mode != AppOpsManager.MODE_ALLOWED) { + return mode; + } + } + if (mWriteOp != AppOpsManager.OP_NONE) { - return mAppOpsManager.noteOp(mWriteOp, Binder.getCallingUid(), callingPkg); + return mAppOpsManager.noteProxyOp(mWriteOp, callingPkg); } + return AppOpsManager.MODE_ALLOWED; } } |