diff options
| author | Svet Ganov <svetoslavganov@google.com> | 2015-06-27 13:15:22 -0700 |
|---|---|---|
| committer | Svet Ganov <svetoslavganov@google.com> | 2015-07-01 16:20:00 -0700 |
| commit | 99b6043dad9d215cf15810b885b6b8c215dd5b5a (patch) | |
| tree | ab714f7926640fbe8dafa4668f251e33e5f915c4 /core/java/android/app | |
| parent | 2438c9b2e7892a8515209cb1d440c3b5147165b2 (diff) | |
| download | frameworks_base-99b6043dad9d215cf15810b885b6b8c215dd5b5a.zip frameworks_base-99b6043dad9d215cf15810b885b6b8c215dd5b5a.tar.gz frameworks_base-99b6043dad9d215cf15810b885b6b8c215dd5b5a.tar.bz2 | |
Teach receivers, activities, providers, and services app ops.
Perform app op check in addition to the permisison check for all four
paltform components - activities, content providers, broadcast receivers,
services - if they are guarded by a permssion that has an associated app
op. This ensures that legacy apps will behave correctly if the permission
of the caller has been revoked, i.e. the app op for that permission was
disabled.
bug:22199666
Change-Id: Ia22d1c38d58b3cd6aabdc655cb7c7bddd85da7a2
Diffstat (limited to 'core/java/android/app')
| -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 |
4 files changed, 117 insertions, 21 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; |
