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

Commit c92df18f authored by Nate Myren's avatar Nate Myren
Browse files

Update permissions flags for all users before restoring

Ensure that permission flags are updated for all users in
setWhitelistedRestrictedPermissions before restoring permission state.

see ag/9286799 and ag/9278208

Fixes: 144690691
Test: atest SplitPermissionTest#inheritGrantedPermissionState
--iterations 10 (run on both user 0 and secondary user)

or

running on secondary user:
$ adb install out/.../CtsAppThatRequestsLocationPermission29.apk
$ adb shell pm grant --user [SECONDARY_USER_ID] android.permission.cts.appthatrequestpermission android.permission.ACCESS_COARSE_LOCATION
$ adb install out/.../CtsAppThatRequestsLocationPermission28.apk
$ adb shell dumpsys package android.permission.cts.appthatrequestpermission

Verify that ACCESS_BACKGROUND_LOCATION is granted to secondary user

Change-Id: I7ca593a807f1fad68504e59e743b736f5f2c915a
parent 27759900
Loading
Loading
Loading
Loading
+109 −94
Original line number Diff line number Diff line
@@ -29,6 +29,9 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAU
import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE;
import static android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME;
import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
@@ -754,9 +757,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
            flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
            flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
            flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
            flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
            flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
            flagValues &= ~FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
            flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
            flagValues &= ~FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
            flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
        }

@@ -1112,13 +1115,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {

            int queryFlags = 0;
            if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0) {
                queryFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
                queryFlags |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
            }
            if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
                queryFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
                queryFlags |= FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
            }
            if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
                queryFlags |=  PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
                queryFlags |=  FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
            }

            ArrayList<String> whitelistedPermissions = null;
@@ -1280,8 +1283,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {

        final long identity = Binder.clearCallingIdentity();
        try {
            setWhitelistedRestrictedPermissionsForUser(
                    pkg, userId, permissions, Process.myUid(), flags, mDefaultPermissionCallback);
            setWhitelistedRestrictedPermissionsForUsers(pkg, new int[]{ userId }, permissions,
                    Process.myUid(), flags, mDefaultPermissionCallback);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
@@ -2517,8 +2520,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                        if (permission.isHardOrSoftRestricted()
                                || permission.isImmutablyRestricted()) {
                            permissionsState.updatePermissionFlags(permission, userId,
                                    PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT,
                                    PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT);
                                    FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT,
                                    FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT);
                        }
                        if (targetSdkVersion < Build.VERSION_CODES.M) {
                            permissionsState.updatePermissionFlags(permission, userId,
@@ -3756,8 +3759,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        }
    }

    private void setWhitelistedRestrictedPermissionsForUser(@NonNull AndroidPackage pkg,
            @UserIdInt int userId, @Nullable List<String> permissions, int callingUid,
    private void setWhitelistedRestrictedPermissionsForUsers(@NonNull AndroidPackage pkg,
            @UserIdInt int[] userIds, @Nullable List<String> permissions, int callingUid,
            @PermissionWhitelistFlags int whitelistFlags, PermissionCallback callback) {
        final PermissionsState permissionsState =
                PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt, pkg);
@@ -3765,12 +3768,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            return;
        }

        ArraySet<String> oldGrantedRestrictedPermissions = null;
        SparseArray<ArraySet<String>> oldGrantedRestrictedPermissions = new SparseArray<>();
        boolean updatePermissions = false;

        final int permissionCount = pkg.getRequestedPermissions().size();
        for (int i = 0; i < permissionCount; i++) {
            final String permissionName = pkg.getRequestedPermissions().get(i);

        for (int i = 0; i < userIds.length; i++) {
            int userId = userIds[i];
            for (int j = 0; j < permissionCount; j++) {
                final String permissionName = pkg.getRequestedPermissions().get(j);

                final BasePermission bp = mSettings.getPermissionLocked(permissionName);

@@ -3779,10 +3784,10 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                }

                if (permissionsState.hasPermission(permissionName, userId)) {
                if (oldGrantedRestrictedPermissions == null) {
                    oldGrantedRestrictedPermissions = new ArraySet<>();
                    if (oldGrantedRestrictedPermissions.get(userId) == null) {
                        oldGrantedRestrictedPermissions.put(userId, new ArraySet<>());
                    }
                oldGrantedRestrictedPermissions.add(permissionName);
                    oldGrantedRestrictedPermissions.get(userId).add(permissionName);
                }

                final int oldFlags = permissionsState.getPermissionFlags(permissionName, userId);
@@ -3795,29 +3800,32 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                    whitelistFlagsCopy &= ~flag;
                    switch (flag) {
                        case FLAG_PERMISSION_WHITELIST_SYSTEM: {
                        mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
                            mask |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
                            if (permissions != null && permissions.contains(permissionName)) {
                            newFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
                                newFlags |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
                            } else {
                            newFlags &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
                                newFlags &= ~FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
                            }
                    } break;
                        }
                        break;
                        case FLAG_PERMISSION_WHITELIST_UPGRADE: {
                        mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
                            mask |= FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
                            if (permissions != null && permissions.contains(permissionName)) {
                            newFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
                                newFlags |= FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
                            } else {
                            newFlags &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
                                newFlags &= ~FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
                            }
                    } break;
                        }
                        break;
                        case FLAG_PERMISSION_WHITELIST_INSTALLER: {
                        mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
                            mask |= FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
                            if (permissions != null && permissions.contains(permissionName)) {
                            newFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
                                newFlags |= FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
                            } else {
                            newFlags &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
                                newFlags &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
                            }
                    } break;
                        }
                        break;
                    }
                }

@@ -3837,7 +3845,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                // as whitelisting trumps policy i.e. policy cannot grant a non
                // grantable permission.
                if ((oldFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
                final boolean isGranted = permissionsState.hasPermission(permissionName, userId);
                    final boolean isGranted = permissionsState.hasPermission(permissionName,
                            userId);
                    if (!isWhitelisted && isGranted) {
                        mask |= PackageManager.FLAG_PERMISSION_POLICY_FIXED;
                        newFlags &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
@@ -3855,19 +3864,27 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                updatePermissionFlagsInternal(permissionName, pkg.getPackageName(), mask, newFlags,
                        callingUid, userId, false, null /*callback*/);
            }
        }

        if (updatePermissions) {
            // Update permission of this app to take into account the new whitelist state.
            restorePermissionState(pkg, false, pkg.getPackageName(), callback);

            // If this resulted in losing a permission we need to kill the app.
            if (oldGrantedRestrictedPermissions != null) {
                final int oldGrantedCount = oldGrantedRestrictedPermissions.size();
                for (int i = 0; i < oldGrantedCount; i++) {
                    final String permission = oldGrantedRestrictedPermissions.valueAt(i);
            for (int i = 0; i < userIds.length; i++) {
                int userId = userIds[i];
                ArraySet<String> oldPermsForUser = oldGrantedRestrictedPermissions.get(userId);
                if (oldPermsForUser == null) {
                    continue;
                }

                final int oldGrantedCount = oldPermsForUser.size();
                for (int j = 0; j < oldGrantedCount; j++) {
                    final String permission = oldPermsForUser.valueAt(j);
                    // Sometimes we create a new permission state instance during update.
                    final PermissionsState newPermissionsState =
                            PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt, pkg);
                            PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt,
                                    pkg);
                    if (!newPermissionsState.hasPermission(permission, userId)) {
                        callback.onPermissionRevoked(pkg.getUid(), userId);
                        break;
@@ -4624,11 +4641,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        public void setWhitelistedRestrictedPermissions(@NonNull AndroidPackage pkg,
                @NonNull int[] userIds, @Nullable List<String> permissions, int callingUid,
                @PackageManager.PermissionWhitelistFlags int flags) {
            for (int userId : userIds) {
                setWhitelistedRestrictedPermissionsForUser(pkg, userId, permissions,
            setWhitelistedRestrictedPermissionsForUsers(pkg, userIds, permissions,
                    callingUid, flags, mDefaultPermissionCallback);
        }
        }
        @Override
        public void setWhitelistedRestrictedPermissions(String packageName,
                List<String> permissions, int flags, int userId) {