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

Commit ff7b92fc authored by Svetoslav's avatar Svetoslav
Browse files

Shared user retains permissions no longer used by any app on an app update

If an app in a shared user uses permission A and B and these are granted
to the shared user and now an app update is installed that only uses A,
the shared user still ratains the B grant. A shared user should have only
permissions declared as used by its currenlty installed apps.

bug:24736912

Change-Id: Idea6c06bdc236fd481a860cddb379e6ce660ee87
parent e39def48
Loading
Loading
Loading
Loading
+76 −2
Original line number Diff line number Diff line
@@ -8366,6 +8366,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
        boolean runtimePermissionsRevoked = false;
        int[] changedRuntimePermissionUserIds = EMPTY_INT_ARRAY;
        boolean changedInstallPermission = false;
@@ -8375,6 +8376,17 @@ public class PackageManagerService extends IPackageManager.Stub {
            if (!ps.isSharedUser()) {
                origPermissions = new PermissionsState(permissionsState);
                permissionsState.reset();
            } else {
                // We need to know only about runtime permission changes since the
                // calling code always writes the install permissions state but
                // the runtime ones are written only if changed. The only cases of
                // changed runtime permissions here are promotion of an install to
                // runtime and revocation of a runtime from a shared user.
                changedRuntimePermissionUserIds = revokeUnusedSharedUserPermissionsLPw(
                        ps.sharedUser, UserManagerService.getInstance().getUserIds());
                if (!ArrayUtils.isEmpty(changedRuntimePermissionUserIds)) {
                    runtimePermissionsRevoked = true;
                }
            }
        }
@@ -8590,9 +8602,11 @@ public class PackageManagerService extends IPackageManager.Stub {
            ps.installPermissionsFixed = true;
        }
        // Persist the runtime permissions state for users with changes.
        // Persist the runtime permissions state for users with changes. If permissions
        // were revoked because no app in the shared user declares them we have to
        // write synchronously to avoid losing runtime permissions state.
        for (int userId : changedRuntimePermissionUserIds) {
            mSettings.writeRuntimePermissionsForUserLPr(userId, false);
            mSettings.writeRuntimePermissionsForUserLPr(userId, runtimePermissionsRevoked);
        }
    }
@@ -12089,6 +12103,66 @@ public class PackageManagerService extends IPackageManager.Stub {
        }
    }
    private int[] revokeUnusedSharedUserPermissionsLPw(SharedUserSetting su, int[] allUserIds) {
        // Collect all used permissions in the UID
        ArraySet<String> usedPermissions = new ArraySet<>();
        final int packageCount = su.packages.size();
        for (int i = 0; i < packageCount; i++) {
            PackageSetting ps = su.packages.valueAt(i);
            if (ps.pkg == null) {
                continue;
            }
            final int requestedPermCount = ps.pkg.requestedPermissions.size();
            for (int j = 0; j < requestedPermCount; j++) {
                String permission = ps.pkg.requestedPermissions.get(j);
                BasePermission bp = mSettings.mPermissions.get(permission);
                if (bp != null) {
                    usedPermissions.add(permission);
                }
            }
        }
        PermissionsState permissionsState = su.getPermissionsState();
        // Prune install permissions
        List<PermissionState> installPermStates = permissionsState.getInstallPermissionStates();
        final int installPermCount = installPermStates.size();
        for (int i = installPermCount - 1; i >= 0;  i--) {
            PermissionState permissionState = installPermStates.get(i);
            if (!usedPermissions.contains(permissionState.getName())) {
                BasePermission bp = mSettings.mPermissions.get(permissionState.getName());
                if (bp != null) {
                    permissionsState.revokeInstallPermission(bp);
                    permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
                            PackageManager.MASK_PERMISSION_FLAGS, 0);
                }
            }
        }
        int[] runtimePermissionChangedUserIds = EmptyArray.INT;
        // Prune runtime permissions
        for (int userId : allUserIds) {
            List<PermissionState> runtimePermStates = permissionsState
                    .getRuntimePermissionStates(userId);
            final int runtimePermCount = runtimePermStates.size();
            for (int i = runtimePermCount - 1; i >= 0; i--) {
                PermissionState permissionState = runtimePermStates.get(i);
                if (!usedPermissions.contains(permissionState.getName())) {
                    BasePermission bp = mSettings.mPermissions.get(permissionState.getName());
                    if (bp != null) {
                        permissionsState.revokeRuntimePermission(bp, userId);
                        permissionsState.updatePermissionFlags(bp, userId,
                                PackageManager.MASK_PERMISSION_FLAGS, 0);
                        runtimePermissionChangedUserIds = ArrayUtils.appendInt(
                                runtimePermissionChangedUserIds, userId);
                    }
                }
            }
        }
        return runtimePermissionChangedUserIds;
    }
    private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,
            String volumeUuid, int[] allUsers, boolean[] perUserInstalled, PackageInstalledInfo res,
            UserHandle user) {