Merge "Make #getCache and #putCache require INTERACT_ACROSS_USERS."
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index bc7307b..74c1e63 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -16,6 +16,8 @@
package com.android.server.content;
+import static android.content.PermissionChecker.PERMISSION_GRANTED;
+
import android.Manifest;
import android.accounts.Account;
import android.annotation.Nullable;
@@ -1212,7 +1214,7 @@
@RequiresPermission(android.Manifest.permission.CACHE_CONTENT)
public void putCache(String packageName, Uri key, Bundle value, int userId) {
Bundle.setDefusable(value, true);
- enforceCrossUserPermission(userId, TAG);
+ enforceNonFullCrossUserPermission(userId, TAG);
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CACHE_CONTENT, TAG);
mContext.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(),
packageName);
@@ -1234,7 +1236,7 @@
@Override
@RequiresPermission(android.Manifest.permission.CACHE_CONTENT)
public Bundle getCache(String packageName, Uri key, int userId) {
- enforceCrossUserPermission(userId, TAG);
+ enforceNonFullCrossUserPermission(userId, TAG);
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CACHE_CONTENT, TAG);
mContext.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(),
packageName);
@@ -1302,6 +1304,30 @@
}
}
+ /**
+ * Checks if the request is from the system or an app that has {@code INTERACT_ACROSS_USERS} or
+ * {@code INTERACT_ACROSS_USERS_FULL} permission, if the {@code userHandle} is not for the
+ * caller.
+ *
+ * @param userHandle the user handle of the user we want to act on behalf of.
+ * @param message the message to log on security exception.
+ */
+ private void enforceNonFullCrossUserPermission(int userHandle, String message) {
+ final int callingUser = UserHandle.getCallingUserId();
+ if (callingUser == userHandle) {
+ return;
+ }
+
+ int interactAcrossUsersState = mContext.checkCallingOrSelfPermission(
+ Manifest.permission.INTERACT_ACROSS_USERS);
+ if (interactAcrossUsersState == PERMISSION_GRANTED) {
+ return;
+ }
+
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
+ }
+
private static int normalizeSyncable(int syncable) {
if (syncable > 0) {
return SyncStorageEngine.AuthorityInfo.SYNCABLE;