Prevent app check via content provider.

Pass in the calling UID when asking PackageManager to resolve the
content provider. This makes sure PM is resolving the provider based on
the calling UID's permissions and not the system server's permissions.

Bug: 189122544
Bug: 189122545
Test: atest CtsContentTestCases
Test: atest CtsJobSchedulerTestCases
Test: atest FrameworksServicesTests:UriGrantsManagerServiceTest
Change-Id: Iaa421e982fca1e29828eda43f0762893199b5ce1
This commit is contained in:
Kweku Adams
2021-06-18 13:22:13 -07:00
parent 89bc0823de
commit ddca60058e
5 changed files with 64 additions and 16 deletions

View File

@@ -565,6 +565,12 @@ public abstract class PackageManagerInternal implements PackageSettingsSnapshotP
*/
public abstract ProviderInfo resolveContentProvider(String name, int flags, int userId);
/**
* Resolves a content provider intent.
*/
public abstract ProviderInfo resolveContentProvider(String name, int flags, int userId,
int callingUid);
/**
* Track the creator of a new isolated uid.
* @param isolatedUid The newly created isolated uid.

View File

@@ -11608,9 +11608,17 @@ public class PackageManagerService extends IPackageManager.Stub
return resolveContentProviderInternal(name, flags, userId);
}
public ProviderInfo resolveContentProvider(String name, int flags, int userId, int callingUid) {
return resolveContentProviderInternal(name, flags, userId, callingUid);
}
private ProviderInfo resolveContentProviderInternal(String name, int flags, int userId) {
return resolveContentProviderInternal(name, flags, userId, Binder.getCallingUid());
}
private ProviderInfo resolveContentProviderInternal(String name, int flags, int userId,
int callingUid) {
if (!mUserManager.exists(userId)) return null;
final int callingUid = Binder.getCallingUid();
flags = updateFlagsForComponent(flags, userId);
final ProviderInfo providerInfo = mComponentResolver.queryProvider(name, flags, userId);
boolean checkedGrants = false;
@@ -27753,6 +27761,13 @@ public class PackageManagerService extends IPackageManager.Stub
name, flags, userId);
}
@Override
public ProviderInfo resolveContentProvider(String name, int flags, int userId,
int callingUid) {
return PackageManagerService.this.resolveContentProviderInternal(
name, flags, userId, callingUid);
}
@Override
public void addIsolatedUid(int isolatedUid, int ownerUid) {
synchronized (mLock) {

View File

@@ -1061,6 +1061,12 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
PackageManager.GET_URI_PERMISSION_PATTERNS | pmFlags, userHandle);
}
private ProviderInfo getProviderInfo(String authority, int userHandle, int pmFlags,
int callingUid) {
return mPmInternal.resolveContentProvider(authority,
PackageManager.GET_URI_PERMISSION_PATTERNS | pmFlags, userHandle, callingUid);
}
/**
* Check if the targetPkg can be granted permission to access uri by
* the callingUid using the given modeFlags. Throws a security exception
@@ -1106,7 +1112,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
final String authority = grantUri.uri.getAuthority();
final ProviderInfo pi = getProviderInfo(authority, grantUri.sourceUserId,
MATCH_DEBUG_TRIAGED_MISSING);
MATCH_DEBUG_TRIAGED_MISSING, callingUid);
if (pi == null) {
Slog.w(TAG, "No content provider found for permission check: " +
grantUri.uri.toSafeString());

View File

@@ -292,23 +292,29 @@ public class UriGrantsManagerServiceTest {
intent.setClipData(clip);
{
// When granting towards primary, persistable can't be honored so
// the entire grant fails
try {
mService.checkGrantUriPermissionFromIntent(
intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY);
fail();
} catch (SecurityException expected) {
// The camera package shouldn't be able to see other packages or their providers,
// so make sure the grant only succeeds for the camera's URIs.
final NeededUriGrants nug = mService.checkGrantUriPermissionFromIntent(
intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY);
if (nug != null && nug.uris != null) {
for (GrantUri gu : nug.uris) {
if (!gu.uri.getAuthority().equals(PKG_CAMERA)) {
fail();
}
}
}
}
{
// When granting towards secondary, persistable can't be honored so
// the entire grant fails
try {
mService.checkGrantUriPermissionFromIntent(
intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_SECONDARY);
fail();
} catch (SecurityException expected) {
// The camera package shouldn't be able to see other packages or their providers,
// so make sure the grant only succeeds for the camera's URIs.
final NeededUriGrants nug = mService.checkGrantUriPermissionFromIntent(
intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_SECONDARY);
if (nug != null && nug.uris != null) {
for (GrantUri gu : nug.uris) {
if (!gu.uri.getAuthority().equals(PKG_CAMERA)) {
fail();
}
}
}
}
}

View File

@@ -135,14 +135,29 @@ public class UriGrantsMockContext extends ContextWrapper {
when(mPmInternal.resolveContentProvider(eq(PKG_CAMERA), anyInt(), eq(userId)))
.thenReturn(buildCameraProvider(userId));
when(mPmInternal.resolveContentProvider(eq(PKG_CAMERA), anyInt(), eq(userId),
eq(UserHandle.getUid(userId, UID_CAMERA))))
.thenReturn(buildCameraProvider(userId));
when(mPmInternal.resolveContentProvider(eq(PKG_PRIVATE), anyInt(), eq(userId)))
.thenReturn(buildPrivateProvider(userId));
when(mPmInternal.resolveContentProvider(eq(PKG_PRIVATE), anyInt(), eq(userId),
eq(UserHandle.getUid(userId, UID_PRIVATE))))
.thenReturn(buildPrivateProvider(userId));
when(mPmInternal.resolveContentProvider(eq(PKG_PUBLIC), anyInt(), eq(userId)))
.thenReturn(buildPublicProvider(userId));
when(mPmInternal.resolveContentProvider(eq(PKG_PUBLIC), anyInt(), eq(userId),
eq(UserHandle.getUid(userId, UID_PUBLIC))))
.thenReturn(buildPublicProvider(userId));
when(mPmInternal.resolveContentProvider(eq(PKG_FORCE), anyInt(), eq(userId)))
.thenReturn(buildForceProvider(userId));
when(mPmInternal.resolveContentProvider(eq(PKG_FORCE), anyInt(), eq(userId),
eq(UserHandle.getUid(userId, UID_FORCE))))
.thenReturn(buildForceProvider(userId));
when(mPmInternal.resolveContentProvider(eq(PKG_COMPLEX), anyInt(), eq(userId)))
.thenReturn(buildComplexProvider(userId));
when(mPmInternal.resolveContentProvider(eq(PKG_COMPLEX), anyInt(), eq(userId),
eq(UserHandle.getUid(userId, UID_COMPLEX))))
.thenReturn(buildComplexProvider(userId));
}
}