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
This commit is contained in:
Chad Brubaker
2017-03-02 15:56:43 -08:00
parent 748bf77274
commit 34ffba62b3

View File

@@ -255,8 +255,8 @@ public class ClipboardService extends SystemService {
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 @@ public class ClipboardService extends SystemService {
@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 @@ public class ClipboardService extends SystemService {
@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 @@ public class ClipboardService extends SystemService {
@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 @@ public class ClipboardService extends SystemService {
@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 @@ public class ClipboardService extends SystemService {
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 @@ public class ClipboardService extends SystemService {
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;
}
}
}