Merge "Fix visibility was gone after updating"

This commit is contained in:
Jackal Guo
2021-08-25 00:21:42 +00:00
committed by Android (Google) Code Review
6 changed files with 104 additions and 19 deletions

View File

@@ -479,6 +479,35 @@ public abstract class PackageManagerInternal implements PackageSettingsSnapshotP
@AppIdInt int recipientAppId, int visibleUid,
boolean direct);
/**
* Grants implicit access based on an interaction between two apps. This grants access to the
* from one application to the other's package metadata.
* <p>
* When an application explicitly tries to interact with another application [via an
* activity, service or provider that is either declared in the caller's
* manifest via the {@code <queries>} tag or has been exposed via the target apps manifest using
* the {@code visibleToInstantApp} attribute], the target application must be able to see
* metadata about the calling app. If the calling application uses an implicit intent [ie
* action VIEW, category BROWSABLE], it remains hidden from the launched app.
* <p>
* If an interaction is not explicit, the {@code direct} argument should be set to false as
* visibility should not be granted in some cases. This method handles that logic.
* <p>
* @param userId the user
* @param intent the intent that triggered the grant
* @param recipientAppId The app ID of the application that is being given access to {@code
* visibleUid}
* @param visibleUid The uid of the application that is becoming accessible to {@code
* recipientAppId}
* @param direct true if the access is being made due to direct interaction between visibleUid
* and recipientAppId.
* @param retainOnUpdate true if the implicit access is retained across package update.
*/
public abstract void grantImplicitAccess(
@UserIdInt int userId, Intent intent,
@AppIdInt int recipientAppId, int visibleUid,
boolean direct, boolean retainOnUpdate);
public abstract boolean isInstantAppInstallerComponent(ComponentName component);
/**
* Prunes instant apps and state associated with uninstalled

View File

@@ -96,6 +96,13 @@ public class AppsFilter implements Watchable, Snappable {
*/
private final SparseSetArray<Integer> mImplicitlyQueryable = new SparseSetArray<>();
/**
* This contains a list of app UIDs that are implicitly queryable because another app explicitly
* interacted with it, but could keep across package updates. For example, if application A
* grants persistable uri permission to application B; regardless of any manifest entries.
*/
private final SparseSetArray<Integer> mRetainedImplicitlyQueryable = new SparseSetArray<>();
/**
* A mapping from the set of App IDs that query other App IDs via package name to the
* list of packages that they can see.
@@ -256,6 +263,7 @@ public class AppsFilter implements Watchable, Snappable {
*/
private AppsFilter(AppsFilter orig) {
Snapshots.copy(mImplicitlyQueryable, orig.mImplicitlyQueryable);
Snapshots.copy(mRetainedImplicitlyQueryable, orig.mRetainedImplicitlyQueryable);
Snapshots.copy(mQueriesViaPackage, orig.mQueriesViaPackage);
Snapshots.copy(mQueriesViaComponent, orig.mQueriesViaComponent);
Snapshots.copy(mQueryableViaUsesLibrary, orig.mQueryableViaUsesLibrary);
@@ -633,15 +641,19 @@ public class AppsFilter implements Watchable, Snappable {
*
* @param recipientUid the uid gaining visibility of the {@code visibleUid}.
* @param visibleUid the uid becoming visible to the {@recipientUid}
* @param retainOnUpdate if the implicit access retained across package updates.
* @return {@code true} if implicit access was not already granted.
*/
public boolean grantImplicitAccess(int recipientUid, int visibleUid) {
public boolean grantImplicitAccess(int recipientUid, int visibleUid, boolean retainOnUpdate) {
if (recipientUid == visibleUid) {
return false;
}
final boolean changed = mImplicitlyQueryable.add(recipientUid, visibleUid);
final boolean changed = retainOnUpdate
? mRetainedImplicitlyQueryable.add(recipientUid, visibleUid)
: mImplicitlyQueryable.add(recipientUid, visibleUid);
if (changed && DEBUG_LOGGING) {
Slog.i(TAG, "implicit access granted: " + recipientUid + " -> " + visibleUid);
Slog.i(TAG, (retainOnUpdate ? "retained " : "") + "implicit access granted: "
+ recipientUid + " -> " + visibleUid);
}
synchronized (mCacheLock) {
if (mShouldFilterCache != null) {
@@ -677,7 +689,7 @@ public class AppsFilter implements Watchable, Snappable {
try {
if (isReplace) {
// let's first remove any prior rules for this package
removePackage(newPkgSetting);
removePackage(newPkgSetting, true /*isReplace*/);
}
mStateProvider.runWithState((settings, users) -> {
ArraySet<String> additionalChangedPackages =
@@ -1078,8 +1090,9 @@ public class AppsFilter implements Watchable, Snappable {
* Removes a package for consideration when filtering visibility between apps.
*
* @param setting the setting of the package being removed.
* @param isReplace if the package is being replaced.
*/
public void removePackage(PackageSetting setting) {
public void removePackage(PackageSetting setting, boolean isReplace) {
mStateProvider.runWithState((settings, users) -> {
final int userCount = users.length;
for (int u = 0; u < userCount; u++) {
@@ -1089,6 +1102,16 @@ public class AppsFilter implements Watchable, Snappable {
for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) {
mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i), removingUid);
}
if (isReplace) {
continue;
}
mRetainedImplicitlyQueryable.remove(removingUid);
for (int i = mRetainedImplicitlyQueryable.size() - 1; i >= 0; i--) {
mRetainedImplicitlyQueryable.remove(
mRetainedImplicitlyQueryable.keyAt(i), removingUid);
}
}
if (!mQueriesViaComponentRequireRecompute) {
@@ -1412,6 +1435,24 @@ public class AppsFilter implements Watchable, Snappable {
}
}
try {
if (DEBUG_TRACING) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mRetainedImplicitlyQueryable");
}
final int targetUid = UserHandle.getUid(targetUserId, targetAppId);
if (mRetainedImplicitlyQueryable.contains(callingUid, targetUid)) {
if (DEBUG_LOGGING) {
log(callingSetting, targetPkgSetting,
"retained implicitly queryable for user");
}
return false;
}
} finally {
if (DEBUG_TRACING) {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
try {
if (DEBUG_TRACING) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mOverlayReferenceMapper");
@@ -1550,6 +1591,9 @@ public class AppsFilter implements Watchable, Snappable {
dumpQueriesMap(pw,
filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId),
mImplicitlyQueryable, " ", expandPackages);
dumpQueriesMap(pw,
filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId),
mRetainedImplicitlyQueryable, " ", expandPackages);
}
pw.println(" queryable via uses-library:");
dumpQueriesMap(pw, filteringAppId, mQueryableViaUsesLibrary, " ", expandPackages);

View File

@@ -18051,7 +18051,8 @@ public class PackageManagerService extends IPackageManager.Stub
synchronized (mLock) {
mDomainVerificationManager.clearPackage(deletedPs.name);
mSettings.getKeySetManagerService().removeAppKeySetDataLPw(packageName);
mAppsFilter.removePackage(getPackageSetting(packageName));
mAppsFilter.removePackage(getPackageSetting(packageName),
false /* isReplace */);
removedAppId = mSettings.removePackageLPw(packageName);
if (outInfo != null) {
outInfo.mRemovedAppId = removedAppId;
@@ -23787,6 +23788,13 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public void grantImplicitAccess(int userId, Intent intent,
int recipientAppId, int visibleUid, boolean direct) {
grantImplicitAccess(userId, intent, recipientAppId, visibleUid, direct,
false /* retainOnUpdate */);
}
@Override
public void grantImplicitAccess(int userId, Intent intent,
int recipientAppId, int visibleUid, boolean direct, boolean retainOnUpdate) {
synchronized (mLock) {
final AndroidPackage visiblePackage = getPackage(visibleUid);
final int recipientUid = UserHandle.getUid(userId, recipientAppId);
@@ -23807,7 +23815,8 @@ public class PackageManagerService extends IPackageManager.Stub
accessGranted = mInstantAppRegistry.grantInstantAccessLPw(userId, intent,
recipientAppId, UserHandle.getAppId(visibleUid) /*instantAppId*/);
} else {
accessGranted = mAppsFilter.grantImplicitAccess(recipientUid, visibleUid);
accessGranted = mAppsFilter.grantImplicitAccess(recipientUid, visibleUid,
retainOnUpdate);
}
if (accessGranted) {
ApplicationPackageManager.invalidateGetPackagesForUidCache();
@@ -24747,7 +24756,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
int visibleUid = providerInfo.applicationInfo.uid;
mPmInternal.grantImplicitAccess(userId, null /*Intent*/, UserHandle.getAppId(recipientUid),
visibleUid, false);
visibleUid, false /*direct*/);
}
boolean canHaveOatDir(String packageName) {

View File

@@ -706,10 +706,10 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
sourcePkg, targetPkg, targetUid, grantUri);
perm.initPersistedModes(modeFlags, createdTime);
mPmInternal.grantImplicitAccess(
targetUserId, null,
targetUserId, null /* intent */,
UserHandle.getAppId(targetUid),
pi.applicationInfo.uid,
false /* direct */);
false /* direct */, true /* retainOnUpdate */);
}
} else {
Slog.w(TAG, "Persisted grant for " + uri + " had source " + sourcePkg
@@ -773,8 +773,9 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
perm = findOrCreateUriPermissionLocked(pi.packageName, targetPkg, targetUid, grantUri);
}
perm.grantModes(modeFlags, owner);
mPmInternal.grantImplicitAccess(UserHandle.getUserId(targetUid), null,
UserHandle.getAppId(targetUid), pi.applicationInfo.uid, false /*direct*/);
mPmInternal.grantImplicitAccess(UserHandle.getUserId(targetUid), null /*intent*/,
UserHandle.getAppId(targetUid), pi.applicationInfo.uid, false /*direct*/,
(modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0);
}
/** Like grantUriPermissionUnchecked, but takes an Intent. */
@@ -1187,7 +1188,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
// provider supports granting permissions
mPmInternal.grantImplicitAccess(
UserHandle.getUserId(targetUid), null,
UserHandle.getAppId(targetUid), pi.applicationInfo.uid, false);
UserHandle.getAppId(targetUid), pi.applicationInfo.uid, false /*direct*/);
return -1;
}

View File

@@ -829,7 +829,7 @@ public class AppsFilterTest {
assertTrue(appsFilter.shouldFilterApplication(DUMMY_OVERLAY_APPID, overlaySetting,
actorSetting, SYSTEM_USER));
appsFilter.removePackage(targetSetting);
appsFilter.removePackage(targetSetting, false /* isReplace */);
// Actor loses visibility to the overlay via removal of the target
assertTrue(appsFilter.shouldFilterApplication(DUMMY_ACTOR_APPID, actorSetting,
@@ -1074,7 +1074,8 @@ public class AppsFilterTest {
watcher.verifyNoChangeReported("getVisibility");
// provider read
appsFilter.grantImplicitAccess(hasProviderAppId, queriesProviderAppId);
appsFilter.grantImplicitAccess(hasProviderAppId, queriesProviderAppId,
false /* retainOnUpdate */);
watcher.verifyChangeReported("grantImplicitAccess");
// ensure implicit access is included in the filter
@@ -1143,7 +1144,8 @@ public class AppsFilterTest {
watcher.verifyNoChangeReported("get");
// provider read
appsFilter.grantImplicitAccess(hasProviderAppId, queriesProviderAppId);
appsFilter.grantImplicitAccess(
hasProviderAppId, queriesProviderAppId, false /* retainOnUpdate */);
watcher.verifyChangeReported("grantImplicitAccess");
// ensure implicit access is included in the filter
@@ -1154,7 +1156,7 @@ public class AppsFilterTest {
watcher.verifyNoChangeReported("get");
// remove a package
appsFilter.removePackage(seesNothing);
appsFilter.removePackage(seesNothing, false /* isReplace */);
watcher.verifyChangeReported("removePackage");
}

View File

@@ -73,8 +73,8 @@ public class UriGrantsManagerServiceTest {
// we expect the following only during grant if a grant is expected
private void verifyNoVisibilityGrant() {
verify(mContext.mPmInternal, never())
.grantImplicitAccess(anyInt(), any(), anyInt(), anyInt(), anyBoolean());
verify(mContext.mPmInternal, never()).grantImplicitAccess(
anyInt(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean());
}
@Before