Merge "Allowing content uris with cloneUserId to be accessed by parent user." into udc-dev

This commit is contained in:
Himanshu Gupta
2023-05-11 21:49:20 +00:00
committed by Android (Google) Code Review

View File

@@ -145,7 +145,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
private boolean mExported; private boolean mExported;
private boolean mNoPerms; private boolean mNoPerms;
private boolean mSingleUser; private boolean mSingleUser;
private SparseBooleanArray mUsersRedirectedToOwner = new SparseBooleanArray(); private SparseBooleanArray mUsersRedirectedToOwnerForMedia = new SparseBooleanArray();
private ThreadLocal<AttributionSource> mCallingAttributionSource; private ThreadLocal<AttributionSource> mCallingAttributionSource;
@@ -874,34 +874,42 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
return true; return true;
} }
if (isAuthorityRedirectedForCloneProfile(mAuthority)) { // Provider user-id will be determined from User Space of the calling app.
if (mUsersRedirectedToOwner.indexOfKey(callingUserId) >= 0) { return isContentRedirectionAllowedForUser(callingUserId);
return mUsersRedirectedToOwner.get(callingUserId); }
/**
* Verify that content redirection is allowed or not.
* We check:
* 1. Type of Authority
* 2. UserProperties allow content sharing
*
* @param incomingUserId - Provider's user-id to be passed should be based upon:
* 1. If client is a cloned app running in user 10, it should be that (10)
* 2. If client is accessing content by hinting user space of content,
* like sysUi (residing in user 0) accessing 'content://11@media/external'
* then it should be 11.
*/
private boolean isContentRedirectionAllowedForUser(int incomingUserId) {
if (MediaStore.AUTHORITY.equals(mAuthority)) {
if (mUsersRedirectedToOwnerForMedia.indexOfKey(incomingUserId) >= 0) {
return mUsersRedirectedToOwnerForMedia.valueAt(incomingUserId);
} }
// Haven't seen this user yet, look it up // Haven't seen this user yet, look it up
try { UserManager um = mContext.getSystemService(UserManager.class);
UserHandle callingUser = UserHandle.getUserHandleForUid(uid); if (um != null && um.getUserProperties(UserHandle.of(incomingUserId))
Context callingUserContext = mContext.createPackageContextAsUser("system", .isMediaSharedWithParent()) {
0, callingUser); UserHandle parent = um.getProfileParent(UserHandle.of(incomingUserId));
UserManager um = callingUserContext.getSystemService(UserManager.class); if (parent != null && parent.equals(myUserHandle())) {
mUsersRedirectedToOwnerForMedia.put(incomingUserId, true);
if (um != null && um.isCloneProfile()) { return true;
UserHandle parent = um.getProfileParent(callingUser);
if (parent != null && parent.equals(myUserHandle())) {
mUsersRedirectedToOwner.put(callingUserId, true);
return true;
}
} }
} catch (PackageManager.NameNotFoundException e) {
// ignore
} }
mUsersRedirectedToOwner.put(callingUserId, false); mUsersRedirectedToOwnerForMedia.put(incomingUserId, false);
return false; return false;
} }
return false; return false;
} }
@@ -2734,7 +2742,11 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
String auth = uri.getAuthority(); String auth = uri.getAuthority();
if (!mSingleUser) { if (!mSingleUser) {
int userId = getUserIdFromAuthority(auth, UserHandle.USER_CURRENT); int userId = getUserIdFromAuthority(auth, UserHandle.USER_CURRENT);
if (userId != UserHandle.USER_CURRENT && userId != mContext.getUserId()) { if (userId != UserHandle.USER_CURRENT
&& userId != mContext.getUserId()
// Since userId specified in content uri, the provider userId would be
// determined from it.
&& !isContentRedirectionAllowedForUser(userId)) {
throw new SecurityException("trying to query a ContentProvider in user " throw new SecurityException("trying to query a ContentProvider in user "
+ mContext.getUserId() + " with a uri belonging to user " + userId); + mContext.getUserId() + " with a uri belonging to user " + userId);
} }