Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a35f11b authored by Jackal Guo's avatar Jackal Guo
Browse files

Fix visibility was gone after updating

System grants implicit visibility when the Uri permission is granted.
But, all the visibility rules would be cleared when package updating.
Since the implict visibility doesn't come from manifest, we cannot
restore it via recompuating visibility. This solution is similar to
how UriGrantsManagerService handles the granted Uri permissions when
packagea updated. We keep them unchanged instead of clearing them.

Bug: 161912313
Test: atest AppsFilterTest
Test: atest AppEnumerationTests
Test: atest UriGrantsManagerServiceTest
Test: manually use test APKs on buganizer to verify
Change-Id: I3026e06574f78c15dbf60c74db126679c677adb1
parent 32f23c94
Loading
Loading
Loading
Loading
+29 −0
Original line number Original line Diff line number Diff line
@@ -479,6 +479,35 @@ public abstract class PackageManagerInternal implements PackageSettingsSnapshotP
            @AppIdInt int recipientAppId, int visibleUid,
            @AppIdInt int recipientAppId, int visibleUid,
            boolean direct);
            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);
    public abstract boolean isInstantAppInstallerComponent(ComponentName component);
    /**
    /**
     * Prunes instant apps and state associated with uninstalled
     * Prunes instant apps and state associated with uninstalled
+49 −5
Original line number Original line Diff line number Diff line
@@ -96,6 +96,13 @@ public class AppsFilter implements Watchable, Snappable {
     */
     */
    private final SparseSetArray<Integer> mImplicitlyQueryable = new SparseSetArray<>();
    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
     * 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.
     * list of packages that they can see.
@@ -256,6 +263,7 @@ public class AppsFilter implements Watchable, Snappable {
     */
     */
    private AppsFilter(AppsFilter orig) {
    private AppsFilter(AppsFilter orig) {
        Snapshots.copy(mImplicitlyQueryable, orig.mImplicitlyQueryable);
        Snapshots.copy(mImplicitlyQueryable, orig.mImplicitlyQueryable);
        Snapshots.copy(mRetainedImplicitlyQueryable, orig.mRetainedImplicitlyQueryable);
        Snapshots.copy(mQueriesViaPackage, orig.mQueriesViaPackage);
        Snapshots.copy(mQueriesViaPackage, orig.mQueriesViaPackage);
        Snapshots.copy(mQueriesViaComponent, orig.mQueriesViaComponent);
        Snapshots.copy(mQueriesViaComponent, orig.mQueriesViaComponent);
        Snapshots.copy(mQueryableViaUsesLibrary, orig.mQueryableViaUsesLibrary);
        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 recipientUid the uid gaining visibility of the {@code visibleUid}.
     * @param visibleUid   the uid becoming visible to the {@recipientUid}
     * @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.
     * @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) {
        if (recipientUid == visibleUid) {
            return false;
            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) {
        if (changed && DEBUG_LOGGING) {
            Slog.i(TAG, "implicit access granted: " + recipientUid + " -> " + visibleUid);
            Slog.i(TAG, (retainOnUpdate ? "retained " : "") + "implicit access granted: "
                    + recipientUid + " -> " + visibleUid);
        }
        }
        synchronized (mCacheLock) {
        synchronized (mCacheLock) {
            if (mShouldFilterCache != null) {
            if (mShouldFilterCache != null) {
@@ -677,7 +689,7 @@ public class AppsFilter implements Watchable, Snappable {
        try {
        try {
            if (isReplace) {
            if (isReplace) {
                // let's first remove any prior rules for this package
                // let's first remove any prior rules for this package
                removePackage(newPkgSetting);
                removePackage(newPkgSetting, true /*isReplace*/);
            }
            }
            mStateProvider.runWithState((settings, users) -> {
            mStateProvider.runWithState((settings, users) -> {
                ArraySet<String> additionalChangedPackages =
                ArraySet<String> additionalChangedPackages =
@@ -1078,8 +1090,9 @@ public class AppsFilter implements Watchable, Snappable {
     * Removes a package for consideration when filtering visibility between apps.
     * Removes a package for consideration when filtering visibility between apps.
     *
     *
     * @param setting the setting of the package being removed.
     * @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) -> {
        mStateProvider.runWithState((settings, users) -> {
            final int userCount = users.length;
            final int userCount = users.length;
            for (int u = 0; u < userCount; u++) {
            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--) {
                for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) {
                    mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i), removingUid);
                    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) {
            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 {
            try {
                if (DEBUG_TRACING) {
                if (DEBUG_TRACING) {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mOverlayReferenceMapper");
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mOverlayReferenceMapper");
@@ -1550,6 +1591,9 @@ public class AppsFilter implements Watchable, Snappable {
            dumpQueriesMap(pw,
            dumpQueriesMap(pw,
                    filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId),
                    filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId),
                    mImplicitlyQueryable, "      ", expandPackages);
                    mImplicitlyQueryable, "      ", expandPackages);
            dumpQueriesMap(pw,
                    filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId),
                    mRetainedImplicitlyQueryable, "      ", expandPackages);
        }
        }
        pw.println("  queryable via uses-library:");
        pw.println("  queryable via uses-library:");
        dumpQueriesMap(pw, filteringAppId, mQueryableViaUsesLibrary, "    ", expandPackages);
        dumpQueriesMap(pw, filteringAppId, mQueryableViaUsesLibrary, "    ", expandPackages);
+12 −3
Original line number Original line Diff line number Diff line
@@ -18050,7 +18050,8 @@ public class PackageManagerService extends IPackageManager.Stub
                synchronized (mLock) {
                synchronized (mLock) {
                    mDomainVerificationManager.clearPackage(deletedPs.name);
                    mDomainVerificationManager.clearPackage(deletedPs.name);
                    mSettings.getKeySetManagerService().removeAppKeySetDataLPw(packageName);
                    mSettings.getKeySetManagerService().removeAppKeySetDataLPw(packageName);
                    mAppsFilter.removePackage(getPackageSetting(packageName));
                    mAppsFilter.removePackage(getPackageSetting(packageName),
                            false /* isReplace */);
                    removedAppId = mSettings.removePackageLPw(packageName);
                    removedAppId = mSettings.removePackageLPw(packageName);
                    if (outInfo != null) {
                    if (outInfo != null) {
                        outInfo.mRemovedAppId = removedAppId;
                        outInfo.mRemovedAppId = removedAppId;
@@ -23668,6 +23669,13 @@ public class PackageManagerService extends IPackageManager.Stub
        @Override
        @Override
        public void grantImplicitAccess(int userId, Intent intent,
        public void grantImplicitAccess(int userId, Intent intent,
                int recipientAppId, int visibleUid, boolean direct) {
                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) {
            synchronized (mLock) {
                final AndroidPackage visiblePackage = getPackage(visibleUid);
                final AndroidPackage visiblePackage = getPackage(visibleUid);
                final int recipientUid = UserHandle.getUid(userId, recipientAppId);
                final int recipientUid = UserHandle.getUid(userId, recipientAppId);
@@ -23688,7 +23696,8 @@ public class PackageManagerService extends IPackageManager.Stub
                    accessGranted = mInstantAppRegistry.grantInstantAccessLPw(userId, intent,
                    accessGranted = mInstantAppRegistry.grantInstantAccessLPw(userId, intent,
                            recipientAppId, UserHandle.getAppId(visibleUid) /*instantAppId*/);
                            recipientAppId, UserHandle.getAppId(visibleUid) /*instantAppId*/);
                } else {
                } else {
                    accessGranted = mAppsFilter.grantImplicitAccess(recipientUid, visibleUid);
                    accessGranted = mAppsFilter.grantImplicitAccess(recipientUid, visibleUid,
                            retainOnUpdate);
                }
                }
                if (accessGranted) {
                if (accessGranted) {
                    ApplicationPackageManager.invalidateGetPackagesForUidCache();
                    ApplicationPackageManager.invalidateGetPackagesForUidCache();
@@ -24628,7 +24637,7 @@ public class PackageManagerService extends IPackageManager.Stub
        }
        }
        int visibleUid = providerInfo.applicationInfo.uid;
        int visibleUid = providerInfo.applicationInfo.uid;
        mPmInternal.grantImplicitAccess(userId, null /*Intent*/, UserHandle.getAppId(recipientUid),
        mPmInternal.grantImplicitAccess(userId, null /*Intent*/, UserHandle.getAppId(recipientUid),
                visibleUid, false);
                visibleUid, false /*direct*/);
    }
    }
    boolean canHaveOatDir(String packageName) {
    boolean canHaveOatDir(String packageName) {
+6 −5
Original line number Original line Diff line number Diff line
@@ -706,10 +706,10 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
                                        sourcePkg, targetPkg, targetUid, grantUri);
                                        sourcePkg, targetPkg, targetUid, grantUri);
                                perm.initPersistedModes(modeFlags, createdTime);
                                perm.initPersistedModes(modeFlags, createdTime);
                                mPmInternal.grantImplicitAccess(
                                mPmInternal.grantImplicitAccess(
                                        targetUserId, null,
                                        targetUserId, null /* intent */,
                                        UserHandle.getAppId(targetUid),
                                        UserHandle.getAppId(targetUid),
                                        pi.applicationInfo.uid,
                                        pi.applicationInfo.uid,
                                        false /* direct */);
                                        false /* direct */, true /* retainOnUpdate */);
                            }
                            }
                        } else {
                        } else {
                            Slog.w(TAG, "Persisted grant for " + uri + " had source " + sourcePkg
                            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 = findOrCreateUriPermissionLocked(pi.packageName, targetPkg, targetUid, grantUri);
        }
        }
        perm.grantModes(modeFlags, owner);
        perm.grantModes(modeFlags, owner);
        mPmInternal.grantImplicitAccess(UserHandle.getUserId(targetUid), null,
        mPmInternal.grantImplicitAccess(UserHandle.getUserId(targetUid), null /*intent*/,
                UserHandle.getAppId(targetUid), pi.applicationInfo.uid, false /*direct*/);
                UserHandle.getAppId(targetUid), pi.applicationInfo.uid, false /*direct*/,
                (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0);
    }
    }


    /** Like grantUriPermissionUnchecked, but takes an Intent. */
    /** Like grantUriPermissionUnchecked, but takes an Intent. */
@@ -1187,7 +1188,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
            // provider supports granting permissions
            // provider supports granting permissions
            mPmInternal.grantImplicitAccess(
            mPmInternal.grantImplicitAccess(
                    UserHandle.getUserId(targetUid), null,
                    UserHandle.getUserId(targetUid), null,
                    UserHandle.getAppId(targetUid), pi.applicationInfo.uid, false);
                    UserHandle.getAppId(targetUid), pi.applicationInfo.uid, false /*direct*/);
            return -1;
            return -1;
        }
        }


+6 −4
Original line number Original line Diff line number Diff line
@@ -829,7 +829,7 @@ public class AppsFilterTest {
        assertTrue(appsFilter.shouldFilterApplication(DUMMY_OVERLAY_APPID, overlaySetting,
        assertTrue(appsFilter.shouldFilterApplication(DUMMY_OVERLAY_APPID, overlaySetting,
                actorSetting, SYSTEM_USER));
                actorSetting, SYSTEM_USER));


        appsFilter.removePackage(targetSetting);
        appsFilter.removePackage(targetSetting, false /* isReplace */);


        // Actor loses visibility to the overlay via removal of the target
        // Actor loses visibility to the overlay via removal of the target
        assertTrue(appsFilter.shouldFilterApplication(DUMMY_ACTOR_APPID, actorSetting,
        assertTrue(appsFilter.shouldFilterApplication(DUMMY_ACTOR_APPID, actorSetting,
@@ -1074,7 +1074,8 @@ public class AppsFilterTest {
        watcher.verifyNoChangeReported("getVisibility");
        watcher.verifyNoChangeReported("getVisibility");


        // provider read
        // provider read
        appsFilter.grantImplicitAccess(hasProviderAppId, queriesProviderAppId);
        appsFilter.grantImplicitAccess(hasProviderAppId, queriesProviderAppId,
                false /* retainOnUpdate */);
        watcher.verifyChangeReported("grantImplicitAccess");
        watcher.verifyChangeReported("grantImplicitAccess");


        // ensure implicit access is included in the filter
        // ensure implicit access is included in the filter
@@ -1143,7 +1144,8 @@ public class AppsFilterTest {
        watcher.verifyNoChangeReported("get");
        watcher.verifyNoChangeReported("get");


        // provider read
        // provider read
        appsFilter.grantImplicitAccess(hasProviderAppId, queriesProviderAppId);
        appsFilter.grantImplicitAccess(
                hasProviderAppId, queriesProviderAppId, false /* retainOnUpdate */);
        watcher.verifyChangeReported("grantImplicitAccess");
        watcher.verifyChangeReported("grantImplicitAccess");


        // ensure implicit access is included in the filter
        // ensure implicit access is included in the filter
@@ -1154,7 +1156,7 @@ public class AppsFilterTest {
        watcher.verifyNoChangeReported("get");
        watcher.verifyNoChangeReported("get");


        // remove a package
        // remove a package
        appsFilter.removePackage(seesNothing);
        appsFilter.removePackage(seesNothing, false /* isReplace */);
        watcher.verifyChangeReported("removePackage");
        watcher.verifyChangeReported("removePackage");
    }
    }


Loading