From df9329334234f3d62ef608d92a958b74981edaaf Mon Sep 17 00:00:00 2001 From: Nicholas Sauer Date: Tue, 27 Aug 2019 08:43:23 -0700 Subject: [PATCH] DO NOT MERGE Update permissions flags for all users before attempting to restore permissions. bug: 140274903 Test: cts-tradefed run cts-dev -m CtsPermissionTestCases -t android.permission.cts.SplitPermissionTest on both user 0 and user 10. Also (running on u10): $ adb install out/.../CtsAppThatRequestsLocationPermission29.apk $ adb shell pm grant --user 10 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 user 10 Change-Id: I3cd4365ca5abce292a190ca7abca4e4e8fbf61c4 --- .../permission/PermissionManagerService.java | 202 +++++++++--------- 1 file changed, 105 insertions(+), 97 deletions(-) diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 899f8022dc8d7..58cbbec55f1d4 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -2022,16 +2022,6 @@ public class PermissionManagerService { return whitelistedPermissions; } - private void setWhitelistedRestrictedPermissions(@NonNull PackageParser.Package pkg, - @NonNull int[] userIds, @Nullable List permissions, int callingUid, - @PackageManager.PermissionWhitelistFlags int whitelistFlags, - @NonNull PermissionCallback callback) { - for (int userId : userIds) { - setWhitelistedRestrictedPermissionsForUser(pkg, userId, permissions, - callingUid, whitelistFlags, callback); - } - } - private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId, String[] grantedPermissions, int callingUid, PermissionCallback callback) { PackageSetting ps = (PackageSetting) pkg.mExtras; @@ -2312,109 +2302,122 @@ public class PermissionManagerService { } } - private void setWhitelistedRestrictedPermissionsForUser(@NonNull PackageParser.Package pkg, - @UserIdInt int userId, @Nullable List permissions, int callingUid, - @PermissionWhitelistFlags int whitelistFlags, PermissionCallback callback) { + private void setWhitelistedRestrictedPermissions(@NonNull PackageParser.Package pkg, + @NonNull int[] userIds, @Nullable List permissions, int callingUid, + @PackageManager.PermissionWhitelistFlags int whitelistFlags, + @NonNull PermissionCallback callback) { + final PackageSetting ps = (PackageSetting) pkg.mExtras; if (ps == null) { return; } final PermissionsState permissionsState = ps.getPermissionsState(); - - ArraySet oldGrantedRestrictedPermissions = null; + SparseArray> oldGrantedRestrictedPermissionsByUser = new SparseArray<>(); boolean updatePermissions = false; final int permissionCount = pkg.requestedPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - final String permissionName = pkg.requestedPermissions.get(i); + for (int userId : userIds) { + for (int i = 0; i < permissionCount; i++) { + final String permissionName = pkg.requestedPermissions.get(i); - final BasePermission bp = mSettings.getPermissionLocked(permissionName); - if (bp == null) { - Slog.w(TAG, "Cannot whitelist unknown permission: " + permissionName); - continue; - } - - if (!bp.isHardOrSoftRestricted()) { - continue; - } - - if (permissionsState.hasPermission(permissionName, userId)) { - if (oldGrantedRestrictedPermissions == null) { - oldGrantedRestrictedPermissions = new ArraySet<>(); + final BasePermission bp = mSettings.getPermissionLocked(permissionName); + if (bp == null) { + Slog.w(TAG, "Cannot whitelist unknown permission: " + permissionName); + continue; } - oldGrantedRestrictedPermissions.add(permissionName); - } - final int oldFlags = permissionsState.getPermissionFlags(permissionName, userId); - - int newFlags = oldFlags; - int mask = 0; - int whitelistFlagsCopy = whitelistFlags; - while (whitelistFlagsCopy != 0) { - final int flag = 1 << Integer.numberOfTrailingZeros(whitelistFlagsCopy); - whitelistFlagsCopy &= ~flag; - switch (flag) { - case FLAG_PERMISSION_WHITELIST_SYSTEM: { - mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT; - if (permissions != null && permissions.contains(permissionName)) { - newFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT; - } else { - newFlags &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT; - } - } break; - case FLAG_PERMISSION_WHITELIST_UPGRADE: { - mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT; - if (permissions != null && permissions.contains(permissionName)) { - newFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT; - } else { - newFlags &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT; - } - } break; - case FLAG_PERMISSION_WHITELIST_INSTALLER: { - mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT; - if (permissions != null && permissions.contains(permissionName)) { - newFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT; - } else { - newFlags &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT; - } - } break; + if (!bp.isHardOrSoftRestricted()) { + continue; } - } - if (oldFlags == newFlags) { - continue; - } - - updatePermissions = true; - - final boolean wasWhitelisted = (oldFlags - & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0; - final boolean isWhitelisted = (newFlags - & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0; - - // If the permission is policy fixed as granted but it is no longer - // on any of the whitelists we need to clear the policy fixed flag - // 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); - if (!isWhitelisted && isGranted) { - mask |= PackageManager.FLAG_PERMISSION_POLICY_FIXED; - newFlags &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED; + if (permissionsState.hasPermission(permissionName, userId)) { + if (oldGrantedRestrictedPermissionsByUser.get(userId) == null) { + oldGrantedRestrictedPermissionsByUser.put(userId, new ArraySet<>()); + } + oldGrantedRestrictedPermissionsByUser.get(userId).add(permissionName); } - } - // If we are whitelisting an app that does not support runtime permissions - // we need to make sure it goes through the permission review UI at launch. - if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M - && !wasWhitelisted && isWhitelisted) { - mask |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; - newFlags |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; - } + final int oldFlags = permissionsState.getPermissionFlags(permissionName, userId); - updatePermissionFlags(permissionName, pkg.packageName, mask, newFlags, - callingUid, userId, false, null /*callback*/); + int newFlags = oldFlags; + int mask = 0; + int whitelistFlagsCopy = whitelistFlags; + while (whitelistFlagsCopy != 0) { + final int flag = 1 << Integer.numberOfTrailingZeros(whitelistFlagsCopy); + whitelistFlagsCopy &= ~flag; + switch (flag) { + case FLAG_PERMISSION_WHITELIST_SYSTEM: { + mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT; + if (permissions != null && permissions.contains(permissionName)) { + newFlags |= + PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT; + } else { + newFlags &= + ~PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT; + } + } + break; + case FLAG_PERMISSION_WHITELIST_UPGRADE: { + mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT; + if (permissions != null && permissions.contains(permissionName)) { + newFlags |= + PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT; + } else { + newFlags &= + ~PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT; + } + } + break; + case FLAG_PERMISSION_WHITELIST_INSTALLER: { + mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT; + if (permissions != null && permissions.contains(permissionName)) { + newFlags |= + PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT; + } else { + newFlags &= ~PackageManager + .FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT; + } + } + break; + } + } + + if (oldFlags == newFlags) { + continue; + } + + updatePermissions = true; + + final boolean wasWhitelisted = (oldFlags + & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0; + final boolean isWhitelisted = (newFlags + & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0; + + // If the permission is policy fixed as granted but it is no longer + // on any of the whitelists we need to clear the policy fixed flag + // 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); + if (!isWhitelisted && isGranted) { + mask |= PackageManager.FLAG_PERMISSION_POLICY_FIXED; + newFlags &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED; + } + } + + // If we are whitelisting an app that does not support runtime permissions + // we need to make sure it goes through the permission review UI at launch. + if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M + && !wasWhitelisted && isWhitelisted) { + mask |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; + newFlags |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; + } + + updatePermissionFlags(permissionName, pkg.packageName, mask, newFlags, + callingUid, userId, false, null /*callback*/); + } } if (updatePermissions) { @@ -2422,7 +2425,12 @@ public class PermissionManagerService { restorePermissionState(pkg, false, pkg.packageName, callback); // If this resulted in losing a permission we need to kill the app. - if (oldGrantedRestrictedPermissions != null) { + int oldGrantedRestrictedPermissionsByUserCount = + oldGrantedRestrictedPermissionsByUser.size(); + for (int j = 0; j < oldGrantedRestrictedPermissionsByUserCount; j++) { + final int userId = oldGrantedRestrictedPermissionsByUser.keyAt(j); + final ArraySet oldGrantedRestrictedPermissions = + oldGrantedRestrictedPermissionsByUser.valueAt(j); final int oldGrantedCount = oldGrantedRestrictedPermissions.size(); for (int i = 0; i < oldGrantedCount; i++) { final String permission = oldGrantedRestrictedPermissions.valueAt(i);