diff options
author | Philip P. Moltmann <moltmann@google.com> | 2018-04-12 13:48:13 -0700 |
---|---|---|
committer | JP Sugarbroad <jpsugar@google.com> | 2018-05-08 14:04:01 -0700 |
commit | a758d64c24f6b9b9ae859e352c0dc292e8b49684 (patch) | |
tree | 9120f992cea7749273506712b2ee56dbcc2c92b9 | |
parent | 2c36d0cfcab59c120bc3419d0788571164acefc9 (diff) | |
download | base-a758d64c24f6b9b9ae859e352c0dc292e8b49684.tar.gz |
DO NOT MERGE (N) Revoke permision when group changed
If a run time permission of a group is already granted we grant the
other permission of the group automatically when requested.
Hence if an already granted permission changed its group during an
update suddenly permission of a potentially not approved group will
get auto-granted.
This is undesirable, hence we revoke the permission during the update
process.
Test: atest android.permission.cts.PermissionGroupChange
Bug: 72710897
Change-Id: Ib2165d1ae53b80455ebe02e07775853e37a2e339
(cherry picked from commit 5aee5696276650e992c813a778e4e7b6e723f331)
-rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index b6a994081229..7095a7695382 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -165,6 +165,7 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.hardware.display.DisplayManager; import android.net.Uri; +import android.os.AsyncTask; import android.os.Binder; import android.os.Build; import android.os.Bundle; @@ -4212,6 +4213,81 @@ public class PackageManagerService extends IPackageManager.Stub { killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED); } + /** + * We might auto-grant permissions if any permission of the group is already granted. Hence if + * the group of a granted permission changes we need to revoke it to avoid having permissions of + * the new group auto-granted. + * + * @param newPackage The new package that was installed + * @param oldPackage The old package that was updated + * @param allPackageNames All package names + */ + private void revokeRuntimePermissionsIfGroupChanged( + PackageParser.Package newPackage, + PackageParser.Package oldPackage, + ArrayList<String> allPackageNames) { + final int numOldPackagePermissions = oldPackage.permissions.size(); + final ArrayMap<String, String> oldPermissionNameToGroupName + = new ArrayMap<>(numOldPackagePermissions); + + for (int i = 0; i < numOldPackagePermissions; i++) { + final PackageParser.Permission permission = oldPackage.permissions.get(i); + + if (permission.group != null) { + oldPermissionNameToGroupName.put(permission.info.name, + permission.group.info.name); + } + } + + final int numNewPackagePermissions = newPackage.permissions.size(); + for (int newPermissionNum = 0; newPermissionNum < numNewPackagePermissions; + newPermissionNum++) { + final PackageParser.Permission newPermission = + newPackage.permissions.get(newPermissionNum); + final int newProtection = newPermission.info.protectionLevel; + + if ((newProtection & PermissionInfo.PROTECTION_DANGEROUS) != 0) { + final String permissionName = newPermission.info.name; + final String newPermissionGroupName = + newPermission.group == null ? null : newPermission.group.info.name; + final String oldPermissionGroupName = oldPermissionNameToGroupName.get( + permissionName); + + if (newPermissionGroupName != null + && !newPermissionGroupName.equals(oldPermissionGroupName)) { + final List<UserInfo> users = mContext.getSystemService(UserManager.class) + .getUsers(); + + final int numUsers = users.size(); + for (int userNum = 0; userNum < numUsers; userNum++) { + final int userId = users.get(userNum).id; + final int numPackages = allPackageNames.size(); + for (int packageNum = 0; packageNum < numPackages; packageNum++) { + final String packageName = allPackageNames.get(packageNum); + + if (checkPermission(permissionName, packageName, userId) + == PackageManager.PERMISSION_GRANTED) { + EventLog.writeEvent(0x534e4554, "72710897", + newPackage.applicationInfo.uid, + "Revoking permission", permissionName, "from package", + packageName, "as the group changed from", + oldPermissionGroupName, "to", newPermissionGroupName); + + try { + revokeRuntimePermission(packageName, permissionName, userId); + } catch (IllegalArgumentException e) { + Slog.e(TAG, "Could not revoke " + permissionName + " from " + + packageName, e); + } + } + } + } + } + } + } + } + + @Override public void resetRuntimePermissions() { mContext.enforceCallingOrSelfPermission( @@ -8113,6 +8189,8 @@ public class PackageManagerService extends IPackageManager.Stub { Log.d(TAG, "Scanning package " + pkg.packageName); } + final PackageParser.Package oldPkg; + synchronized (mPackages) { if (mPackages.containsKey(pkg.packageName) || mSharedLibraries.containsKey(pkg.packageName)) { @@ -8121,6 +8199,13 @@ public class PackageManagerService extends IPackageManager.Stub { + " already installed. Skipping duplicate."); } + final PackageSetting oldPkgSetting = mSettings.peekPackageLPr(pkg.packageName); + if (oldPkgSetting == null) { + oldPkg = null; + } else { + oldPkg = oldPkgSetting.pkg; + } + // If we're only installing presumed-existing packages, require that the // scanned APK is both already known and at the path previously established // for it. Previously unknown packages we pick up normally, but if we have an @@ -8993,6 +9078,24 @@ public class PackageManagerService extends IPackageManager.Stub { // This is a regular package, with one or more known overlay packages. createIdmapsForPackageLI(pkg); } + + if (oldPkg != null) { + // We need to call revokeRuntimePermissionsIfGroupChanged async as permission + // revokation from this method might need to kill apps which need the + // mPackages lock on a different thread. This would dead lock. + // + // Hence create a copy of all package names and pass it into + // revokeRuntimePermissionsIfGroupChanged. Only for those permissions might get + // revoked. If a new package is added before the async code runs the permission + // won't be granted yet, hence new packages are no problem. + final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet()); + + AsyncTask.execute(new Runnable() { + public void run() { + revokeRuntimePermissionsIfGroupChanged(pkg, oldPkg, allPackageNames); + } + }); + } } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); |