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

Commit 2c443b17 authored by Hai Zhang's avatar Hai Zhang
Browse files

Properly fix revokePermissionsNoLongerImplicitLocked() for shared UIDs.

This is actually a follow up to ag/13938162 that will properly fix the
shared UID handling.

If there are multiple packages in the same shared UID, the target SDK
version of the UID should be the lowest target SDK version of those
packages. This is also confirmed by existing code in
PermissionManagerService and PackageManagerService.

However, the current implicit permission revocation is only reading
from the implicit permissions of the particular package, which is
determined during package parsing according to the target SDK version
of that package. So if a permission in one package in the shared UID
is becoming explicit, it breaks the other package if it still relies
on the permission being implicitly. And in reality, it's hard to make
sure the other package has been updated to handle this situation.

So in order to properly fix this, we need to collect all the implicit
permissions in this shared UID and pass that to the revocation
logic. This does mean we will be doing exactly the same thing again
when we are handling other packages' permission state, but that won't
be a big issue, whereas the alternative is to refactor the code to
handle permission state by UID which is way too risky for T or
backports. In the proposed new permission subsystem, we will indeed
handle permissions by UID though.

Bug: 201263297
Test: presubmit
Change-Id: I8315dc27b703d819e8970134d5cf17b0edbc22dc
Merged-In: I8315dc27b703d819e8970134d5cf17b0edbc22dc
parent a789b926
Loading
Loading
Loading
Loading
+36 −30
Original line number Diff line number Diff line
@@ -2679,31 +2679,36 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            }
        }

        synchronized (mLock) {
            for (final int userId : userIds) {
                final UserPermissionState userState = mState.getOrCreateUserState(userId);
                final UidPermissionState uidState = userState.getOrCreateUidState(ps.getAppId());

                if (uidState.isMissing()) {
        Collection<String> uidRequestedPermissions;
                    int targetSdkVersion;
        Collection<String> uidImplicitPermissions;
        int uidTargetSdkVersion;
        if (!ps.isSharedUser()) {
            uidRequestedPermissions = pkg.getRequestedPermissions();
                        targetSdkVersion = pkg.getTargetSdkVersion();
            uidImplicitPermissions = pkg.getImplicitPermissions();
            uidTargetSdkVersion = pkg.getTargetSdkVersion();
        } else {
            uidRequestedPermissions = new ArraySet<>();
                        targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
            uidImplicitPermissions = new ArraySet<>();
            uidTargetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
            List<AndroidPackage> packages = ps.getSharedUser().getPackages();
            int packagesSize = packages.size();
            for (int i = 0; i < packagesSize; i++) {
                AndroidPackage sharedUserPackage = packages.get(i);
                uidRequestedPermissions.addAll(
                        sharedUserPackage.getRequestedPermissions());
                            targetSdkVersion = Math.min(targetSdkVersion,
                uidImplicitPermissions.addAll(
                        sharedUserPackage.getImplicitPermissions());
                uidTargetSdkVersion = Math.min(uidTargetSdkVersion,
                        sharedUserPackage.getTargetSdkVersion());
            }
        }

        synchronized (mLock) {
            for (final int userId : userIds) {
                final UserPermissionState userState = mState.getOrCreateUserState(userId);
                final UidPermissionState uidState = userState.getOrCreateUidState(ps.getAppId());

                if (uidState.isMissing()) {
                    for (String permissionName : uidRequestedPermissions) {
                        Permission permission = mRegistry.getPermission(permissionName);
                        if (permission == null) {
@@ -2717,7 +2722,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                                        FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT,
                                        FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT);
                            }
                            if (targetSdkVersion < Build.VERSION_CODES.M) {
                            if (uidTargetSdkVersion < Build.VERSION_CODES.M) {
                                uidState.updatePermissionFlags(permission,
                                        PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
                                                | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT,
@@ -3043,8 +3048,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                    userState.setInstallPermissionsFixed(ps.name, true);
                }

                updatedUserIds = revokePermissionsNoLongerImplicitLocked(uidState, pkg,
                        userId, updatedUserIds);
                updatedUserIds = revokePermissionsNoLongerImplicitLocked(uidState,
                        pkg.getPackageName(), uidImplicitPermissions, uidTargetSdkVersion, userId,
                        updatedUserIds);
                updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origState,
                        uidState, pkg, newImplicitPermissions, userId, updatedUserIds);
            }
@@ -3081,7 +3087,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
     * {@link PackageManager#FLAG_PERMISSION_REVOKE_WHEN_REQUESTED} set.
     *
     * @param ps The state of the permissions of the package
     * @param pkg The package that is currently looked at
     * @param packageName The name of the package
     * @param uidImplicitPermissions The implicit permissions of all packages in the UID
     * @param uidTargetSdkVersion The lowest target SDK version of all packages in the UID
     * @param userIds All user IDs in the system, must be passed in because this method is locked
     * @param updatedUserIds a list of user ids that needs to be amended if the permission state
     *                       for a user is changed.
@@ -3090,14 +3098,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
     */
    @GuardedBy("mLock")
    private @NonNull int[] revokePermissionsNoLongerImplicitLocked(@NonNull UidPermissionState ps,
            @NonNull AndroidPackage pkg, int userId, @NonNull int[] updatedUserIds) {
        String pkgName = pkg.getPackageName();
        boolean supportsRuntimePermissions = pkg.getTargetSdkVersion()
                >= Build.VERSION_CODES.M;
            @NonNull String packageName, @NonNull Collection<String> uidImplicitPermissions,
            int uidTargetSdkVersion, int userId, @NonNull int[] updatedUserIds) {
        boolean supportsRuntimePermissions = uidTargetSdkVersion >= Build.VERSION_CODES.M;

        for (String permission : ps.getGrantedPermissions()) {
            if (pkg.getRequestedPermissions().contains(permission)
                    && !pkg.getImplicitPermissions().contains(permission)) {
            if (!uidImplicitPermissions.contains(permission)) {
                Permission bp = mRegistry.getPermission(permission);
                if (bp != null && bp.isRuntime()) {
                    int flags = ps.getPermissionFlags(permission);
@@ -3124,7 +3130,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                            if (ps.revokePermission(bp)) {
                                if (DEBUG_PERMISSIONS) {
                                    Slog.i(TAG, "Revoking runtime permission "
                                            + permission + " for " + pkgName
                                            + permission + " for " + packageName
                                            + " as it is now requested");
                                }
                            }