From 3ba22246d4b1abb84390c00529221f2b89c25d85 Mon Sep 17 00:00:00 2001 From: Hai Zhang Date: Thu, 25 Jun 2020 20:46:12 -0700 Subject: [PATCH] Skip updating flags for a permission that's not requested. If a permission isn't requested, there shouldn't be a PermissionState for it, however updatePermissionFlags() may create such a state and confuse restorePermissionState() for what is a new implicit permission. So don't allow adding a new PermissionState for a permission that's not requested, and make it a no-op because the caller might just have seen an older package and we shouldn't crash them. Updating flags for a permission with an existing PermissionState is still allowed so that a permission state can be erased by revoking and clearing all its flags. See also b/159585979#comment7. Bug: 159585979 Bug: 152580253 Test: atest --rerun-until-failure 100 SplitPermissionTest Test: The test above fails within 2 or 3 attempts without this fix, but passes successfully for 100 times with this fix. Logcat shows that the logic in the fix is hit multiple times during the test. Change-Id: I17d252bdc2cfa65485b7950da099dff73c4979a9 --- .../permission/PermissionManagerService.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) 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 4f0b689996f2a..9963cf7e212d7 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -789,6 +789,31 @@ public class PermissionManagerService extends IPermissionManager.Stub { final PermissionsState permissionsState = ps.getPermissionsState(); final boolean hadState = permissionsState.getRuntimePermissionState(permName, userId) != null; + if (!hadState) { + boolean isRequested = false; + // Fast path, the current package has requested the permission. + if (pkg.getRequestedPermissions().contains(permName)) { + isRequested = true; + } + if (!isRequested) { + // Slow path, go through all shared user packages. + String[] sharedUserPackageNames = + mPackageManagerInt.getSharedUserPackagesForPackage(packageName, userId); + for (String sharedUserPackageName : sharedUserPackageNames) { + AndroidPackage sharedUserPkg = mPackageManagerInt.getPackage( + sharedUserPackageName); + if (sharedUserPkg != null + && sharedUserPkg.getRequestedPermissions().contains(permName)) { + isRequested = true; + break; + } + } + } + if (!isRequested) { + Log.e(TAG, "Permission " + permName + " isn't requested by package " + packageName); + return; + } + } final boolean permissionUpdated = permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues); if (permissionUpdated && bp.isRuntime()) {