summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSvet Ganov <svetoslavganov@google.com>2015-06-27 13:15:22 -0700
committerSvet Ganov <svetoslavganov@google.com>2015-07-01 16:20:00 -0700
commit99b6043dad9d215cf15810b885b6b8c215dd5b5a (patch)
treeab714f7926640fbe8dafa4668f251e33e5f915c4
parent2438c9b2e7892a8515209cb1d440c3b5147165b2 (diff)
downloadframeworks_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
-rw-r--r--api/current.txt2
-rw-r--r--api/system-current.txt2
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java2
-rw-r--r--core/java/android/app/ActivityManagerNative.java20
-rw-r--r--core/java/android/app/AppOpsManager.java97
-rw-r--r--core/java/android/app/ContextImpl.java10
-rw-r--r--core/java/android/app/IActivityManager.java11
-rw-r--r--core/java/android/content/BroadcastReceiver.java2
-rw-r--r--core/java/android/content/ContentProvider.java24
-rw-r--r--core/java/com/android/internal/app/IAppOpsService.aidl2
-rw-r--r--services/core/java/com/android/server/AppOpsService.java45
-rwxr-xr-xservices/core/java/com/android/server/am/ActiveServices.java32
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java35
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java135
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java113
-rw-r--r--services/core/java/com/android/server/am/PendingIntentRecord.java3
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java3
17 files changed, 419 insertions, 119 deletions
diff --git a/api/current.txt b/api/current.txt
index 3ae5372..07c90bc 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3856,6 +3856,8 @@ package android.app {
method public void finishOp(java.lang.String, int, java.lang.String);
method public int noteOp(java.lang.String, int, java.lang.String);
method public int noteOpNoThrow(java.lang.String, int, java.lang.String);
+ method public int noteProxyOp(java.lang.String, java.lang.String);
+ method public int noteProxyOpNoThrow(java.lang.String, java.lang.String);
method public static java.lang.String permissionToOp(java.lang.String);
method public int startOp(java.lang.String, int, java.lang.String);
method public int startOpNoThrow(java.lang.String, int, java.lang.String);
diff --git a/api/system-current.txt b/api/system-current.txt
index 8a633df..f3167eb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3965,6 +3965,8 @@ package android.app {
method public void finishOp(java.lang.String, int, java.lang.String);
method public int noteOp(java.lang.String, int, java.lang.String);
method public int noteOpNoThrow(java.lang.String, int, java.lang.String);
+ method public int noteProxyOp(java.lang.String, java.lang.String);
+ method public int noteProxyOpNoThrow(java.lang.String, java.lang.String);
method public static java.lang.String permissionToOp(java.lang.String);
method public int startOp(java.lang.String, int, java.lang.String);
method public int startOpNoThrow(java.lang.String, int, java.lang.String);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 13fda59..ca6c6ca 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -767,7 +767,7 @@ public class Am extends BaseCommand {
return;
}
System.out.println("Starting service: " + intent);
- ComponentName cn = mAm.startService(null, intent, intent.getType(), mUserId);
+ ComponentName cn = mAm.startService(null, intent, intent.getType(), null, mUserId);
if (cn == null) {
System.err.println("Error: Not found; no service started.");
} else if (cn.getPackageName().equals("!")) {
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;
}
}
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 86c1b2f..201a124 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -25,6 +25,8 @@ interface IAppOpsService {
// be kept in sync with frameworks/native/include/binder/IAppOpsService.h
int checkOperation(int code, int uid, String packageName);
int noteOperation(int code, int uid, String packageName);
+ int noteProxyOperation(int code, String proxyPackageName,
+ int callingUid, String callingPackageName);
int startOperation(IBinder token, int code, int uid, String packageName);
void finishOperation(IBinder token, int code, int uid, String packageName);
void startWatchingMode(int op, String packageName, IAppOpsCallback callback);
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 79c66b9..f0fc399 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -116,6 +116,8 @@ public class AppOpsService extends IAppOpsService.Stub {
public final static class Op {
public final int uid;
public final String packageName;
+ public int proxyUid = -1;
+ public String proxyPackageName;
public final int op;
public int mode;
public int duration;
@@ -289,7 +291,8 @@ public class AppOpsService extends IAppOpsService.Stub {
for (int j=0; j<pkgOps.size(); j++) {
Op curOp = pkgOps.valueAt(j);
resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
- curOp.rejectTime, curOp.duration));
+ curOp.rejectTime, curOp.duration, curOp.proxyUid,
+ curOp.proxyPackageName));
}
} else {
for (int j=0; j<ops.length; j++) {
@@ -299,7 +302,8 @@ public class AppOpsService extends IAppOpsService.Stub {
resOps = new ArrayList<AppOpsManager.OpEntry>();
}
resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
- curOp.rejectTime, curOp.duration));
+ curOp.rejectTime, curOp.duration, curOp.proxyUid,
+ curOp.proxyPackageName));
}
}
}
@@ -659,9 +663,28 @@ public class AppOpsService extends IAppOpsService.Stub {
}
@Override
+ public int noteProxyOperation(int code, String proxyPackageName,
+ int proxiedUid, String proxiedPackageName) {
+ verifyIncomingOp(code);
+ final int proxyMode = noteOperationUnchecked(code, Binder.getCallingUid(),
+ proxyPackageName, -1, null);
+ if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
+ return proxyMode;
+ }
+ return noteOperationUnchecked(code, proxiedUid, proxiedPackageName,
+ Binder.getCallingUid(), proxyPackageName);
+
+ }
+
+ @Override
public int noteOperation(int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
+ return noteOperationUnchecked(code, uid, packageName, 0, null);
+ }
+
+ private int noteOperationUnchecked(int code, int uid, String packageName,
+ int proxyUid, String proxyPackageName) {
synchronized (this) {
Ops ops = getOpsLocked(uid, packageName, true);
if (ops == null) {
@@ -690,6 +713,8 @@ public class AppOpsService extends IAppOpsService.Stub {
+ " package " + packageName);
op.time = System.currentTimeMillis();
op.rejectTime = 0;
+ op.proxyUid = proxyUid;
+ op.proxyPackageName = proxyPackageName;
return AppOpsManager.MODE_ALLOWED;
}
}
@@ -1051,6 +1076,14 @@ public class AppOpsService extends IAppOpsService.Stub {
if (dur != null) {
op.duration = Integer.parseInt(dur);
}
+ String proxyUid = parser.getAttributeValue(null, "pu");
+ if (proxyUid != null) {
+ op.proxyUid = Integer.parseInt(proxyUid);
+ }
+ String proxyPackageName = parser.getAttributeValue(null, "pp");
+ if (proxyPackageName != null) {
+ op.proxyPackageName = proxyPackageName;
+ }
HashMap<String, Ops> pkgOps = mUidOps.get(uid);
if (pkgOps == null) {
pkgOps = new HashMap<String, Ops>();
@@ -1132,6 +1165,14 @@ public class AppOpsService extends IAppOpsService.Stub {
if (dur != 0) {
out.attribute(null, "d", Integer.toString(dur));
}
+ int proxyUid = op.getProxyUid();
+ if (proxyUid != -1) {
+ out.attribute(null, "pu", Integer.toString(proxyUid));
+ }
+ String proxyPackageName = op.getProxyPackageName();
+ if (proxyPackageName != null) {
+ out.attribute(null, "pp", proxyPackageName);
+ }
out.endTag(null, "op");
}
out.endTag(null, "uid");
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 333db5d..899139f 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -29,6 +29,7 @@ import java.util.List;
import java.util.Set;
import android.app.ActivityThread;
+import android.app.AppOpsManager;
import android.os.Build;
import android.os.DeadObjectException;
import android.os.Handler;
@@ -302,8 +303,8 @@ public final class ActiveServices {
return getServiceMap(callingUser).mServicesByName;
}
- ComponentName startServiceLocked(IApplicationThread caller, Intent service,
- String resolvedType, int callingPid, int callingUid, int userId)
+ ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
+ int callingPid, int callingUid, String callingPackage, int userId)
throws TransactionTooLargeException {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
+ " type=" + resolvedType + " args=" + service.getExtras());
@@ -324,7 +325,7 @@ public final class ActiveServices {
ServiceLookupResult res =
- retrieveServiceLocked(service, resolvedType,
+ retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg);
if (res == null) {
return null;
@@ -490,7 +491,7 @@ public final class ActiveServices {
}
// If this service is active, make sure it is stopped.
- ServiceLookupResult r = retrieveServiceLocked(service, resolvedType,
+ ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, null,
Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false);
if (r != null) {
if (r.record != null) {
@@ -508,8 +509,8 @@ public final class ActiveServices {
return 0;
}
- IBinder peekServiceLocked(Intent service, String resolvedType) {
- ServiceLookupResult r = retrieveServiceLocked(service, resolvedType,
+ IBinder peekServiceLocked(Intent service, String resolvedType, String callingPackage) {
+ ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, callingPackage,
Binder.getCallingPid(), Binder.getCallingUid(),
UserHandle.getCallingUserId(), false, false);
@@ -694,8 +695,8 @@ public final class ActiveServices {
}
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
- String resolvedType, IServiceConnection connection, int flags, int userId)
- throws TransactionTooLargeException {
+ String resolvedType, IServiceConnection connection, int flags,
+ String callingPackage, int userId) throws TransactionTooLargeException {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
+ " type=" + resolvedType + " conn=" + connection.asBinder()
+ " flags=0x" + Integer.toHexString(flags));
@@ -746,7 +747,7 @@ public final class ActiveServices {
final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
ServiceLookupResult res =
- retrieveServiceLocked(service, resolvedType,
+ retrieveServiceLocked(service, resolvedType, callingPackage,
Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);
if (res == null) {
return 0;
@@ -1022,7 +1023,7 @@ public final class ActiveServices {
}
private ServiceLookupResult retrieveServiceLocked(Intent service,
- String resolvedType, int callingPid, int callingUid, int userId,
+ String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
boolean createIfNeeded, boolean callingFromFg) {
ServiceRecord r = null;
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "retrieveServiceLocked: " + service
@@ -1112,7 +1113,18 @@ public final class ActiveServices {
+ ", uid=" + callingUid
+ " requires " + r.permission);
return new ServiceLookupResult(null, r.permission);
+ } else if (r.permission != null && callingPackage != null) {
+ final int opCode = AppOpsManager.permissionToOpCode(r.permission);
+ if (opCode != AppOpsManager.OP_NONE && mAm.mAppOpsService.noteOperation(
+ opCode, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: Accessing service " + r.name
+ + " from pid=" + callingPid
+ + ", uid=" + callingUid
+ + " requires appop " + AppOpsManager.opToName(opCode));
+ return null;
+ }
}
+
if (!mAm.mIntentFirewall.checkService(r.name, service, callingUid, callingPid,
resolvedType, r.appInfo)) {
return null;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 959fd37..6522d40 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15554,13 +15554,18 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
- String resolvedType, int userId) throws TransactionTooLargeException {
+ String resolvedType, String callingPackage, int userId)
+ throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
+ if (callingPackage == null) {
+ throw new IllegalArgumentException("callingPackage cannot be null");
+ }
+
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"startService: " + service + " type=" + resolvedType);
synchronized(this) {
@@ -15568,20 +15573,21 @@ public final class ActivityManagerService extends ActivityManagerNative
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(caller, service,
- resolvedType, callingPid, callingUid, userId);
+ resolvedType, callingPid, callingUid, callingPackage, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
- ComponentName startServiceInPackage(int uid, Intent service, String resolvedType, int userId)
+ ComponentName startServiceInPackage(int uid, Intent service, String resolvedType,
+ String callingPackage, int userId)
throws TransactionTooLargeException {
synchronized(this) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"startServiceInPackage: " + service + " type=" + resolvedType);
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(null, service,
- resolvedType, -1, uid, userId);
+ resolvedType, -1, uid, callingPackage, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
@@ -15602,14 +15608,19 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public IBinder peekService(Intent service, String resolvedType) {
+ public IBinder peekService(Intent service, String resolvedType, String callingPackage) {
enforceNotIsolatedCaller("peekService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
+
+ if (callingPackage == null) {
+ throw new IllegalArgumentException("callingPackage cannot be null");
+ }
+
synchronized(this) {
- return mServices.peekServiceLocked(service, resolvedType);
+ return mServices.peekServiceLocked(service, resolvedType, callingPackage);
}
}
@@ -15779,8 +15790,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
public int bindService(IApplicationThread caller, IBinder token, Intent service,
- String resolvedType, IServiceConnection connection, int flags, int userId)
- throws TransactionTooLargeException {
+ String resolvedType, IServiceConnection connection, int flags, String callingPackage,
+ int userId) throws TransactionTooLargeException {
enforceNotIsolatedCaller("bindService");
// Refuse possible leaked file descriptors
@@ -15788,9 +15799,13 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new IllegalArgumentException("File descriptors passed in Intent");
}
+ if (callingPackage == null) {
+ throw new IllegalArgumentException("callingPackage cannot be null");
+ }
+
synchronized(this) {
- return mServices.bindServiceLocked(caller, token, service, resolvedType,
- connection, flags, userId);
+ return mServices.bindServiceLocked(caller, token, service,
+ resolvedType, connection, flags, callingPackage, userId);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 4ce5c7e..c12aff6 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -187,12 +187,12 @@ public final class ActivityStackSupervisor implements DisplayListener {
Manifest.permission.CALL_PHONE);
}
- /** Action not restricted for the calling package. */
- private static final int ACTION_RESTRICTION_NONE = 0;
- /** Action restricted for the calling package by not granting a used permission. */
- private static final int ACTION_RESTRICTION_PERMISSION = 1;
- /** Action restricted for the calling package by not allowing a used permission's app op. */
- private static final int ACTION_RESTRICTION_APPOP = 2;
+ /** Action restriction: launching the activity is not restricted. */
+ private static final int ACTIVITY_RESTRICTION_NONE = 0;
+ /** Action restriction: launching the activity is restricted by a permission. */
+ private static final int ACTIVITY_RESTRICTION_PERMISSION = 1;
+ /** Action restriction: launching the activity is restricted by an app op. */
+ private static final int ACTIVITY_RESTRICTION_APPOP = 2;
/** Status Bar Service **/
private IBinder mToken = new Binder();
@@ -1539,51 +1539,61 @@ public final class ActivityStackSupervisor implements DisplayListener {
return err;
}
+ boolean abort = false;
+
final int startAnyPerm = mService.checkPermission(
START_ANY_ACTIVITY, callingPid, callingUid);
- final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
- callingUid, aInfo.applicationInfo.uid, aInfo.exported);
- final int actionRestriction = getActionRestrictionForCallingPackage(
- intent.getAction(), callingPackage, callingPid, callingUid);
- if (startAnyPerm != PERMISSION_GRANTED && (componentPerm != PERMISSION_GRANTED
- || actionRestriction == ACTION_RESTRICTION_PERMISSION)) {
- if (resultRecord != null) {
- resultStack.sendActivityResultLocked(-1,
- resultRecord, resultWho, requestCode,
- Activity.RESULT_CANCELED, null);
+ if (startAnyPerm != PERMISSION_GRANTED) {
+ final int componentRestriction = getComponentRestrictionForCallingPackage(
+ aInfo, callingPackage, callingPid, callingUid);
+ final int actionRestriction = getActionRestrictionForCallingPackage(
+ intent.getAction(), callingPackage, callingPid, callingUid);
+
+ if (componentRestriction == ACTIVITY_RESTRICTION_PERMISSION
+ || actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) {
+ if (resultRecord != null) {
+ resultStack.sendActivityResultLocked(-1,
+ resultRecord, resultWho, requestCode,
+ Activity.RESULT_CANCELED, null);
+ }
+ String msg;
+ if (actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) {
+ msg = "Permission Denial: starting " + intent.toString()
+ + " from " + callerApp + " (pid=" + callingPid
+ + ", uid=" + callingUid + ")" + " with revoked permission "
+ + ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction());
+ } else if (!aInfo.exported) {
+ msg = "Permission Denial: starting " + intent.toString()
+ + " from " + callerApp + " (pid=" + callingPid
+ + ", uid=" + callingUid + ")"
+ + " not exported from uid " + aInfo.applicationInfo.uid;
+ } else {
+ msg = "Permission Denial: starting " + intent.toString()
+ + " from " + callerApp + " (pid=" + callingPid
+ + ", uid=" + callingUid + ")"
+ + " requires " + aInfo.permission;
+ }
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
}
- String msg;
- if (actionRestriction == ACTION_RESTRICTION_PERMISSION) {
- msg = "Permission Denial: starting " + intent.toString()
- + " from " + callerApp + " (pid=" + callingPid
- + ", uid=" + callingUid + ")" + " with revoked permission "
- + ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction());
- } else if (!aInfo.exported) {
- msg = "Permission Denial: starting " + intent.toString()
+
+ if (actionRestriction == ACTIVITY_RESTRICTION_APPOP) {
+ String message = "Appop Denial: starting " + intent.toString()
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
- + " not exported from uid " + aInfo.applicationInfo.uid;
- } else {
- msg = "Permission Denial: starting " + intent.toString()
+ + " requires " + AppOpsManager.permissionToOp(
+ ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction()));
+ Slog.w(TAG, message);
+ abort = true;
+ } else if (componentRestriction == ACTIVITY_RESTRICTION_APPOP) {
+ String message = "Appop Denial: starting " + intent.toString()
+ " from " + callerApp + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
- + " requires " + aInfo.permission;
+ + " requires appop " + AppOpsManager.permissionToOp(aInfo.permission);
+ Slog.w(TAG, message);
+ abort = true;
}
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- }
-
- boolean abort = false;
-
- if (startAnyPerm != PERMISSION_GRANTED
- && actionRestriction == ACTION_RESTRICTION_APPOP) {
- String msg = "Permission Denial: starting " + intent.toString()
- + " from " + callerApp + " (pid=" + callingPid
- + ", uid=" + callingUid + ")"
- + " requires " + aInfo.permission;
- Slog.w(TAG, msg);
- abort = true;
}
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
@@ -1664,15 +1674,40 @@ public final class ActivityStackSupervisor implements DisplayListener {
return err;
}
+ private int getComponentRestrictionForCallingPackage(ActivityInfo activityInfo,
+ String callingPackage, int callingPid, int callingUid) {
+ if (activityInfo.permission == null) {
+ return ACTIVITY_RESTRICTION_NONE;
+ }
+
+ if (mService.checkComponentPermission(activityInfo.permission, callingPid, callingUid,
+ activityInfo.applicationInfo.uid, activityInfo.exported)
+ == PackageManager.PERMISSION_DENIED) {
+ return ACTIVITY_RESTRICTION_PERMISSION;
+ }
+
+ final int opCode = AppOpsManager.permissionToOpCode(activityInfo.permission);
+ if (opCode == AppOpsManager.OP_NONE) {
+ return ACTIVITY_RESTRICTION_NONE;
+ }
+
+ if (mService.mAppOpsService.noteOperation(opCode, callingUid,
+ callingPackage) != AppOpsManager.MODE_ALLOWED) {
+ return ACTIVITY_RESTRICTION_APPOP;
+ }
+
+ return ACTIVITY_RESTRICTION_NONE;
+ }
+
private int getActionRestrictionForCallingPackage(String action,
String callingPackage, int callingPid, int callingUid) {
if (action == null) {
- return ACTION_RESTRICTION_NONE;
+ return ACTIVITY_RESTRICTION_NONE;
}
String permission = ACTION_TO_RUNTIME_PERMISSION.get(action);
if (permission == null) {
- return ACTION_RESTRICTION_NONE;
+ return ACTIVITY_RESTRICTION_NONE;
}
final PackageInfo packageInfo;
@@ -1681,29 +1716,29 @@ public final class ActivityStackSupervisor implements DisplayListener {
.getPackageInfo(callingPackage, PackageManager.GET_PERMISSIONS);
} catch (PackageManager.NameNotFoundException e) {
Slog.i(TAG, "Cannot find package info for " + callingPackage);
- return ACTION_RESTRICTION_NONE;
+ return ACTIVITY_RESTRICTION_NONE;
}
if (!ArrayUtils.contains(packageInfo.requestedPermissions, permission)) {
- return ACTION_RESTRICTION_NONE;
+ return ACTIVITY_RESTRICTION_NONE;
}
if (mService.checkPermission(permission, callingPid, callingUid) ==
PackageManager.PERMISSION_DENIED) {
- return ACTION_RESTRICTION_PERMISSION;
+ return ACTIVITY_RESTRICTION_PERMISSION;
}
final int opCode = AppOpsManager.permissionToOpCode(permission);
if (opCode == AppOpsManager.OP_NONE) {
- return ACTION_RESTRICTION_NONE;
+ return ACTIVITY_RESTRICTION_NONE;
}
if (mService.mAppOpsService.noteOperation(opCode, callingUid,
callingPackage) != AppOpsManager.MODE_ALLOWED) {
- return ACTION_RESTRICTION_APPOP;
+ return ACTIVITY_RESTRICTION_APPOP;
}
- return ACTION_RESTRICTION_NONE;
+ return ACTIVITY_RESTRICTION_NONE;
}
ActivityStack computeStackFocus(ActivityRecord r, boolean newTask) {
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 2335071..30aa411 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -463,7 +463,7 @@ public final class BroadcastQueue {
}
}
- private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
+ private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered) {
boolean skip = false;
if (filter.requiredPermission != null) {
@@ -477,9 +477,23 @@ public final class BroadcastQueue {
+ " requires " + filter.requiredPermission
+ " due to registered receiver " + filter);
skip = true;
+ } else {
+ final int opCode = AppOpsManager.permissionToOpCode(filter.requiredPermission);
+ if (opCode != AppOpsManager.OP_NONE
+ && mService.mAppOpsService.noteOperation(opCode, r.callingUid,
+ r.callerPackage) != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: broadcasting "
+ + r.intent.toString()
+ + " from " + r.callerPackage + " (pid="
+ + r.callingPid + ", uid=" + r.callingUid + ")"
+ + " requires appop " + AppOpsManager.permissionToOp(
+ filter.requiredPermission)
+ + " due to registered receiver " + filter);
+ skip = true;
+ }
}
}
- if (!skip && r.requiredPermission != null) {
+ if (!skip) {
int perm = mService.checkComponentPermission(r.requiredPermission,
filter.receiverList.pid, filter.receiverList.uid, -1, true);
if (perm != PackageManager.PERMISSION_GRANTED) {
@@ -493,17 +507,42 @@ public final class BroadcastQueue {
+ " (uid " + r.callingUid + ")");
skip = true;
}
- }
- if (r.appOp != AppOpsManager.OP_NONE) {
- int mode = mService.mAppOpsService.noteOperation(r.appOp,
- filter.receiverList.uid, filter.packageName);
- if (mode != AppOpsManager.MODE_ALLOWED) {
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
- "App op " + r.appOp + " not allowed for broadcast to uid "
- + filter.receiverList.uid + " pkg " + filter.packageName);
- skip = true;
+ int appOp = AppOpsManager.OP_NONE;
+ if (r.requiredPermission != null) {
+ appOp = AppOpsManager.permissionToOpCode(r.requiredPermission);
+ if (appOp != AppOpsManager.OP_NONE
+ && mService.mAppOpsService.noteOperation(appOp,
+ filter.receiverList.uid, filter.packageName)
+ != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: receiving "
+ + r.intent.toString()
+ + " to " + filter.receiverList.app
+ + " (pid=" + filter.receiverList.pid
+ + ", uid=" + filter.receiverList.uid + ")"
+ + " requires appop " + AppOpsManager.permissionToOp(
+ r.requiredPermission)
+ + " due to sender " + r.callerPackage
+ + " (uid " + r.callingUid + ")");
+ skip = true;
+ }
+ }
+ if (!skip && r.appOp != appOp && r.appOp != AppOpsManager.OP_NONE
+ && mService.mAppOpsService.noteOperation(r.appOp,
+ filter.receiverList.uid, filter.packageName)
+ != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: receiving "
+ + r.intent.toString()
+ + " to " + filter.receiverList.app
+ + " (pid=" + filter.receiverList.pid
+ + ", uid=" + filter.receiverList.uid + ")"
+ + " requires appop " + AppOpsManager.permissionToOp(
+ r.requiredPermission)
+ + " due to sender " + r.callerPackage
+ + " (uid " + r.callingUid + ")");
+ skip = true;
}
}
+
if (!skip) {
skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
r.callingPid, r.resolvedType, filter.receiverList.uid);
@@ -804,8 +843,23 @@ public final class BroadcastQueue {
+ " due to receiver " + component.flattenToShortString());
}
skip = true;
+ } else if (info.activityInfo.permission != null) {
+ final int opCode = AppOpsManager.permissionToOpCode(info.activityInfo.permission);
+ if (opCode != AppOpsManager.OP_NONE
+ && mService.mAppOpsService.noteOperation(opCode, r.callingUid,
+ r.callerPackage) != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: broadcasting "
+ + r.intent.toString()
+ + " from " + r.callerPackage + " (pid="
+ + r.callingPid + ", uid=" + r.callingUid + ")"
+ + " requires appop " + AppOpsManager.permissionToOp(
+ info.activityInfo.permission)
+ + " due to registered receiver "
+ + component.flattenToShortString());
+ skip = true;
+ }
}
- if (info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
+ if (!skip && info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
r.requiredPermission != null) {
try {
perm = AppGlobals.getPackageManager().
@@ -825,17 +879,36 @@ public final class BroadcastQueue {
skip = true;
}
}
- if (r.appOp != AppOpsManager.OP_NONE) {
- int mode = mService.mAppOpsService.noteOperation(r.appOp,
- info.activityInfo.applicationInfo.uid, info.activityInfo.packageName);
- if (mode != AppOpsManager.MODE_ALLOWED) {
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
- "App op " + r.appOp + " not allowed for broadcast to uid "
- + info.activityInfo.applicationInfo.uid + " pkg "
- + info.activityInfo.packageName);
+ int appOp = AppOpsManager.OP_NONE;
+ if (!skip && r.requiredPermission != null) {
+ appOp = AppOpsManager.permissionToOpCode(r.requiredPermission);
+ if (appOp != AppOpsManager.OP_NONE
+ && mService.mAppOpsService.noteOperation(appOp,
+ info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
+ != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: receiving "
+ + r.intent + " to "
+ + component.flattenToShortString()
+ + " requires appop " + AppOpsManager.permissionToOp(
+ r.requiredPermission)
+ + " due to sender " + r.callerPackage
+ + " (uid " + r.callingUid + ")");
skip = true;
}
}
+ if (!skip && r.appOp != appOp && r.appOp != AppOpsManager.OP_NONE
+ && mService.mAppOpsService.noteOperation(r.appOp,
+ info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
+ != AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Appop Denial: receiving "
+ + r.intent + " to "
+ + component.flattenToShortString()
+ + " requires appop " + AppOpsManager.permissionToOp(
+ r.requiredPermission)
+ + " due to sender " + r.callerPackage
+ + " (uid " + r.callingUid + ")");
+ skip = true;
+ }
if (!skip) {
skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
r.callingPid, r.resolvedType, info.activityInfo.applicationInfo.uid);
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index ece3ffb..5b46799 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -305,7 +305,8 @@ final class PendingIntentRecord extends IIntentSender.Stub {
break;
case ActivityManager.INTENT_SENDER_SERVICE:
try {
- owner.startServiceInPackage(uid, finalIntent, resolvedType, userId);
+ owner.startServiceInPackage(uid, finalIntent,
+ resolvedType, key.packageName, userId);
} catch (RuntimeException e) {
Slog.w(TAG, "Unable to send startService intent", e);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1385440..f51e679 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -9163,7 +9163,8 @@ public class PackageManagerService extends IPackageManager.Stub {
IActivityManager am = ActivityManagerNative.getDefault();
if (am != null) {
try {
- am.startService(null, intent, null, UserHandle.USER_OWNER);
+ am.startService(null, intent, null, mContext.getOpPackageName(),
+ UserHandle.USER_OWNER);
} catch (RemoteException e) {
}
}