Limit instant app access to clipboard
Instant apps can access the clipboard (both read and write) in order for
copy/paste UI to work correctly. In order to limit the exposure of user
data Instant Apps can only access the clipboard while running in the
foreground.
Longer term it would be nice to gate Instant Apps clipboard access
around user interaction to prevent shenanigains, but this is a good
start.
Test: Manually verified that ClipboardManager.getPrimaryClip returns
null when the instant app transitions out of the foreground
Bug: 34231507
Change-Id: I7ea83e503d249c61e9df2d8bd83028e24705be11
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 94417b5..8abde78 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -255,8 +255,8 @@
clip.getItemAt(0).getText().toString());
}
final int callingUid = Binder.getCallingUid();
- if (mAppOps.noteOp(AppOpsManager.OP_WRITE_CLIPBOARD, callingUid,
- callingPackage) != AppOpsManager.MODE_ALLOWED) {
+ if (!clipboardAccessAllowed(AppOpsManager.OP_WRITE_CLIPBOARD, callingPackage,
+ callingUid)) {
return;
}
checkDataOwnerLocked(clip, callingUid);
@@ -304,8 +304,8 @@
@Override
public ClipData getPrimaryClip(String pkg) {
synchronized (this) {
- if (mAppOps.noteOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
- pkg) != AppOpsManager.MODE_ALLOWED) {
+ if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, pkg,
+ Binder.getCallingUid())) {
return null;
}
addActiveOwnerLocked(Binder.getCallingUid(), pkg);
@@ -316,8 +316,8 @@
@Override
public ClipDescription getPrimaryClipDescription(String callingPackage) {
synchronized (this) {
- if (mAppOps.checkOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
- callingPackage) != AppOpsManager.MODE_ALLOWED) {
+ if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage,
+ Binder.getCallingUid())) {
return null;
}
PerUserClipboard clipboard = getClipboard();
@@ -328,8 +328,8 @@
@Override
public boolean hasPrimaryClip(String callingPackage) {
synchronized (this) {
- if (mAppOps.checkOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
- callingPackage) != AppOpsManager.MODE_ALLOWED) {
+ if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage,
+ Binder.getCallingUid())) {
return false;
}
return getClipboard().primaryClip != null;
@@ -355,8 +355,8 @@
@Override
public boolean hasClipboardText(String callingPackage) {
synchronized (this) {
- if (mAppOps.checkOp(AppOpsManager.OP_READ_CLIPBOARD, Binder.getCallingUid(),
- callingPackage) != AppOpsManager.MODE_ALLOWED) {
+ if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage,
+ Binder.getCallingUid())) {
return false;
}
PerUserClipboard clipboard = getClipboard();
@@ -417,8 +417,9 @@
try {
ListenerInfo li = (ListenerInfo)
clipboard.primaryClipListeners.getBroadcastCookie(i);
- if (mAppOps.checkOpNoThrow(AppOpsManager.OP_READ_CLIPBOARD, li.mUid,
- li.mPackageName) == AppOpsManager.MODE_ALLOWED) {
+
+ if (clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, li.mPackageName,
+ li.mUid)) {
clipboard.primaryClipListeners.getBroadcastItem(i)
.dispatchPrimaryClipChanged();
}
@@ -551,4 +552,24 @@
revokeItemLocked(clipboard.primaryClip.getItemAt(i));
}
}
+
+ private boolean clipboardAccessAllowed(int op, String callingPackage, int callingUid) {
+ // Check the AppOp.
+ if (mAppOps.checkOp(op, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
+ return false;
+ }
+ try {
+ // Installed apps can access the clipboard at any time.
+ if (!AppGlobals.getPackageManager().isInstantApp(callingPackage,
+ UserHandle.getUserId(callingUid))) {
+ return true;
+ }
+ // Instant apps can only access the clipboard if they are in the foreground.
+ return mAm.isAppForeground(callingUid);
+ } catch (RemoteException e) {
+ Slog.e("clipboard", "Failed to get Instant App status for package " + callingPackage,
+ e);
+ return false;
+ }
+ }
}