Allowing content uris with cloneUserId to be accessed by parent user.
In some cases a userId maybe appended to the contentUri, to determine the storage location of the content, ex: `content://10@media/external/images/media/000001.png` This has started in systemui/screenshot, where ag/19783114 appended the userId of the foreground user in ScreenShot Content Uris. However, this change gives error while saving screenshots in cloned apps, as the userId appended is different from the MediaProvider Process trying to save the content (MP of user 0 is used for clonedProfile). The error is triggerred from `ContentProvider.validateIncomingUri` We add the check that if the ContentAuthorityUser shares Media with a parentUser, and the latter is same as the MP process user, we do not throw the above error. Bug: b/270350104 Test: Manual verification on device Change-Id: I62e87c4f04840573138ed59918cc869d1ab12dea
This commit is contained in:
@@ -145,7 +145,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
|
||||
private boolean mExported;
|
||||
private boolean mNoPerms;
|
||||
private boolean mSingleUser;
|
||||
private SparseBooleanArray mUsersRedirectedToOwner = new SparseBooleanArray();
|
||||
private SparseBooleanArray mUsersRedirectedToOwnerForMedia = new SparseBooleanArray();
|
||||
|
||||
private ThreadLocal<AttributionSource> mCallingAttributionSource;
|
||||
|
||||
@@ -874,34 +874,42 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isAuthorityRedirectedForCloneProfile(mAuthority)) {
|
||||
if (mUsersRedirectedToOwner.indexOfKey(callingUserId) >= 0) {
|
||||
return mUsersRedirectedToOwner.get(callingUserId);
|
||||
// Provider user-id will be determined from User Space of the calling app.
|
||||
return isContentRedirectionAllowedForUser(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
|
||||
try {
|
||||
UserHandle callingUser = UserHandle.getUserHandleForUid(uid);
|
||||
Context callingUserContext = mContext.createPackageContextAsUser("system",
|
||||
0, callingUser);
|
||||
UserManager um = callingUserContext.getSystemService(UserManager.class);
|
||||
|
||||
if (um != null && um.isCloneProfile()) {
|
||||
UserHandle parent = um.getProfileParent(callingUser);
|
||||
|
||||
if (parent != null && parent.equals(myUserHandle())) {
|
||||
mUsersRedirectedToOwner.put(callingUserId, true);
|
||||
return true;
|
||||
}
|
||||
UserManager um = mContext.getSystemService(UserManager.class);
|
||||
if (um != null && um.getUserProperties(UserHandle.of(incomingUserId))
|
||||
.isMediaSharedWithParent()) {
|
||||
UserHandle parent = um.getProfileParent(UserHandle.of(incomingUserId));
|
||||
if (parent != null && parent.equals(myUserHandle())) {
|
||||
mUsersRedirectedToOwnerForMedia.put(incomingUserId, true);
|
||||
return true;
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
mUsersRedirectedToOwner.put(callingUserId, false);
|
||||
mUsersRedirectedToOwnerForMedia.put(incomingUserId, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2729,7 +2737,11 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
|
||||
String auth = uri.getAuthority();
|
||||
if (!mSingleUser) {
|
||||
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 "
|
||||
+ mContext.getUserId() + " with a uri belonging to user " + userId);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user