From c5d0555fedacbe1437c89c6648e465d6c2576733 Mon Sep 17 00:00:00 2001 From: Jeongsik Mun Date: Wed, 9 Jun 2021 18:42:01 +0900 Subject: [PATCH] Fix an issue where a custom permission is revoked A normal permission declared by a system app could be revoked when the updated system app is uninstalled. Assume that there are an apk on /system and its updated apk on /data. And both declares the same normal permission and it's granted to non-system apps. At this point, If the updated system is uninstalled, That normal permission will be revoked by uninstalling, but, it won't be granted to non-system apps which had been had the permission when installing the apk on /system. Because install permisisons were already fixed at install time. This fix dosen't revoke normal permissions declared by the disabled system app from apps while uninstalling the updated system app. Bug: 182828078 Test: 1) Add a system app declares A, B permissions 2) Update the system app declares A, B, C, D permissions 3) Install a non-system app requesting A, B, C, D permissions 4) Uninstall the updated system app 5) Verify the non-system app has A, B permissions Change-Id: I866934576dcc8103b123c10b0deb6144a85c67f5 --- .../permission/PermissionManagerService.java | 68 ++++++++++++------- 1 file changed, 43 insertions(+), 25 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 6368d1ed8a2ac..8d3319187e5f0 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -4213,33 +4213,35 @@ public class PermissionManagerService extends IPermissionManager.Stub { // If the target package is being uninstalled, we need to revoke this permission // From all other packages if (pkg == null || !hasPermission(pkg, bp.getName())) { - Slog.i(TAG, "Removing permission " + bp.getName() - + " that used to be declared by " + bp.getPackageName()); - if (bp.isRuntime()) { - final int[] userIds = mUserManagerInt.getUserIds(); - final int numUserIds = userIds.length; - for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) { - final int userId = userIds[userIdNum]; - mPackageManagerInt.forEachPackage((AndroidPackage p) -> - revokePermissionFromPackageForUser(p.getPackageName(), - bp.getName(), true, userId, callback)); - } - } else { - mPackageManagerInt.forEachPackage(p -> { + if (!isPermissionDeclaredByDisabledSystemPkg(bp)) { + Slog.i(TAG, "Removing permission " + bp.getName() + + " that used to be declared by " + bp.getPackageName()); + if (bp.isRuntime()) { final int[] userIds = mUserManagerInt.getUserIds(); - synchronized (mLock) { - for (final int userId : userIds) { - final UidPermissionState uidState = getUidStateLocked(p, - userId); - if (uidState == null) { - Slog.e(TAG, "Missing permissions state for " - + p.getPackageName() + " and user " + userId); - continue; - } - uidState.removePermissionState(bp.getName()); - } + final int numUserIds = userIds.length; + for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) { + final int userId = userIds[userIdNum]; + mPackageManagerInt.forEachPackage((AndroidPackage p) -> + revokePermissionFromPackageForUser(p.getPackageName(), + bp.getName(), true, userId, callback)); } - }); + } else { + mPackageManagerInt.forEachPackage(p -> { + final int[] userIds = mUserManagerInt.getUserIds(); + synchronized (mLock) { + for (final int userId : userIds) { + final UidPermissionState uidState = getUidStateLocked(p, + userId); + if (uidState == null) { + Slog.e(TAG, "Missing permissions state for " + + p.getPackageName() + " and user " + userId); + continue; + } + uidState.removePermissionState(bp.getName()); + } + } + }); + } } synchronized (mLock) { mRegistry.removePermission(bp.getName()); @@ -4264,6 +4266,22 @@ public class PermissionManagerService extends IPermissionManager.Stub { return changed; } + private boolean isPermissionDeclaredByDisabledSystemPkg(@NonNull Permission permission) { + final PackageSetting disabledSourcePs = mPackageManagerInt.getDisabledSystemPackage( + permission.getPackageName()); + if (disabledSourcePs != null && disabledSourcePs.getPkg() != null) { + final String permissionName = permission.getName(); + final List sourcePerms = disabledSourcePs.getPkg().getPermissions(); + for (ParsedPermission sourcePerm : sourcePerms) { + if (TextUtils.equals(permissionName, sourcePerm.getName()) + && permission.getProtectionLevel() == sourcePerm.getProtectionLevel()) { + return true; + } + } + } + return false; + } + /** * Revoke a runtime permission from a package for a given user ID. */