From e0c4b0b2f71ccbe21796f6f413c3efabbc5b664a Mon Sep 17 00:00:00 2001 From: Himanshu Gupta Date: Wed, 21 Jun 2023 13:18:57 +0000 Subject: [PATCH] Allowing content uris with parentUserId to be accessed by cloned user. In ag/21547694 we added a change to allow content uris with clonedUserId to be accessible from parentUser. In this change we fix the reverse part of the flow, by skipping cross-profile user checks in such cases. Bug: 283399640 Test: Manual verification on device Change-Id: Iddf10be61480fd2e9daaa288dca44bc64ebc4308 --- .../server/am/ContentProviderHelper.java | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java index 3ab40d26c9737..e26ee9c9d7474 100644 --- a/services/core/java/com/android/server/am/ContentProviderHelper.java +++ b/services/core/java/com/android/server/am/ContentProviderHelper.java @@ -96,7 +96,9 @@ import com.android.server.sdksandbox.SdkSandboxManagerLocal; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; /** @@ -116,6 +118,8 @@ public class ContentProviderHelper { private final ProviderMap mProviderMap; private boolean mSystemProvidersInstalled; + private final Map mCloneProfileAuthorityRedirectionCache = new HashMap<>(); + ContentProviderHelper(ActivityManagerService service, boolean createProviderMap) { mService = service; mProviderMap = createProviderMap ? new ProviderMap(mService) : null; @@ -201,9 +205,24 @@ public class ContentProviderHelper { final UserProperties userProps = umInternal.getUserProperties(userId); final boolean isMediaSharedWithParent = userProps != null && userProps.isMediaSharedWithParent(); - if (!isAuthorityRedirectedForCloneProfile(name) || !isMediaSharedWithParent) { + if (!isAuthorityRedirectedForCloneProfileCached(name) || !isMediaSharedWithParent) { // First check if this content provider has been published... cpr = mProviderMap.getProviderByName(name, userId); + // In case we are on media authority and callingUid is cloned app asking to access + // the contentProvider of user 0 by specifying content as + // content://@media/external/file, we skip checkUser. + if (isAuthorityRedirectedForCloneProfileCached(name)) { + final int callingUserId = UserHandle.getUserId(callingUid); + final UserProperties userPropsCallingUser = + umInternal.getUserProperties(callingUserId); + final boolean isMediaSharedWithParentForCallingUser = + userPropsCallingUser != null + && userPropsCallingUser.isMediaSharedWithParent(); + if (isMediaSharedWithParentForCallingUser + && umInternal.getProfileParentId(callingUserId) == userId) { + checkCrossUser = false; + } + } } // If that didn't work, check if it exists for user 0 and then // verify that it's a singleton provider before using it. @@ -218,7 +237,7 @@ public class ContentProviderHelper { r == null ? callingUid : r.uid, cpi.applicationInfo.uid)) { userId = UserHandle.USER_SYSTEM; checkCrossUser = false; - } else if (isAuthorityRedirectedForCloneProfile(name)) { + } else if (isAuthorityRedirectedForCloneProfileCached(name)) { if (isMediaSharedWithParent) { userId = umInternal.getProfileParentId(userId); checkCrossUser = false; @@ -1073,7 +1092,7 @@ public class ContentProviderHelper { return false; } - if (isAuthorityRedirectedForCloneProfile(holder.info.authority) + if (isAuthorityRedirectedForCloneProfileCached(holder.info.authority) && resolveParentUserIdForCloneProfile(userId) != userId) { // Since clone profile shares certain providers with its parent and the access is // re-directed as well, the holder may not actually be installed on the clone profile. @@ -1108,7 +1127,7 @@ public class ContentProviderHelper { userId = UserHandle.getCallingUserId(); } - if (isAuthorityRedirectedForCloneProfile(authority)) { + if (isAuthorityRedirectedForCloneProfileCached(authority)) { UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class); UserInfo userInfo = umInternal.getUserInfo(userId); @@ -1954,4 +1973,14 @@ public class ContentProviderHelper { String[] args) { return mProviderMap.dumpProviderProto(fd, pw, name, args); } + + private Boolean isAuthorityRedirectedForCloneProfileCached(String auth) { + if (mCloneProfileAuthorityRedirectionCache.containsKey(auth)) { + return mCloneProfileAuthorityRedirectionCache.get(auth); + } else { + boolean isAuthRedirected = isAuthorityRedirectedForCloneProfile(auth); + mCloneProfileAuthorityRedirectionCache.put(auth, isAuthRedirected); + return isAuthRedirected; + } + } }