From 9f5b0a27350df984fb4a98b9658e89390ed60573 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Thu, 13 Aug 2015 18:25:20 -0700 Subject: Fix issue #22940169: "pm grant" can no longer grant permissions... ...with protection flag PROTECTION_FLAG_DEVELOPMENT Bring back the old grant/revoke code for development permissions. Also some more dumpsys output to help debugging. And new dumpsys command for checking a permission. Change-Id: I6e27e62a9ca5ec1ecc0f102714a448ea02f0f41c --- .../java/com/android/server/pm/BasePermission.java | 6 ++ .../android/server/pm/PackageManagerService.java | 69 ++++++++++++++++------ .../core/java/com/android/server/pm/Settings.java | 34 ++++++++--- 3 files changed, 81 insertions(+), 28 deletions(-) (limited to 'services') diff --git a/services/core/java/com/android/server/pm/BasePermission.java b/services/core/java/com/android/server/pm/BasePermission.java index 18407c9..52d0928 100644 --- a/services/core/java/com/android/server/pm/BasePermission.java +++ b/services/core/java/com/android/server/pm/BasePermission.java @@ -88,4 +88,10 @@ final class BasePermission { return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) == PermissionInfo.PROTECTION_DANGEROUS; } + + public boolean isDevelopment() { + return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) + == PermissionInfo.PROTECTION_SIGNATURE + && (protectionLevel & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0; + } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 21e256e..4403cbe 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -3432,14 +3432,14 @@ public class PackageManagerService extends IPackageManager.Stub { } } - private static void enforceDeclaredAsUsedAndRuntimePermission(PackageParser.Package pkg, + private static void enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(PackageParser.Package pkg, BasePermission bp) { int index = pkg.requestedPermissions.indexOf(bp.name); if (index == -1) { throw new SecurityException("Package " + pkg.packageName + " has not requested permission " + bp.name); } - if (!bp.isRuntime()) { + if (!bp.isRuntime() && !bp.isDevelopment()) { throw new SecurityException("Permission " + bp.name + " is not a changeable permission type"); } @@ -3473,7 +3473,7 @@ public class PackageManagerService extends IPackageManager.Stub { throw new IllegalArgumentException("Unknown permission: " + name); } - enforceDeclaredAsUsedAndRuntimePermission(pkg, bp); + enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(pkg, bp); uid = UserHandle.getUid(userId, pkg.applicationInfo.uid); sb = (SettingBase) pkg.mExtras; @@ -3489,6 +3489,16 @@ public class PackageManagerService extends IPackageManager.Stub { + name + " for package: " + packageName); } + if (bp.isDevelopment()) { + // Development permissions must be handled specially, since they are not + // normal runtime permissions. For now they apply to all users. + if (permissionsState.grantInstallPermission(bp) != + PermissionsState.PERMISSION_OPERATION_FAILURE) { + scheduleWriteSettingsLocked(); + } + return; + } + final int result = permissionsState.grantRuntimePermission(bp, userId); switch (result) { case PermissionsState.PERMISSION_OPERATION_FAILURE: { @@ -3557,7 +3567,7 @@ public class PackageManagerService extends IPackageManager.Stub { throw new IllegalArgumentException("Unknown permission: " + name); } - enforceDeclaredAsUsedAndRuntimePermission(pkg, bp); + enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(pkg, bp); SettingBase sb = (SettingBase) pkg.mExtras; if (sb == null) { @@ -3572,6 +3582,16 @@ public class PackageManagerService extends IPackageManager.Stub { + name + " for package: " + packageName); } + if (bp.isDevelopment()) { + // Development permissions must be handled specially, since they are not + // normal runtime permissions. For now they apply to all users. + if (permissionsState.revokeInstallPermission(bp) != + PermissionsState.PERMISSION_OPERATION_FAILURE) { + scheduleWriteSettingsLocked(); + } + return; + } + if (permissionsState.revokeRuntimePermission(bp, userId) == PermissionsState.PERMISSION_OPERATION_FAILURE) { return; @@ -3799,21 +3819,6 @@ public class PackageManagerService extends IPackageManager.Stub { return (flags & PackageManager.FLAG_PERMISSION_USER_SET) != 0; } - void grantInstallPermissionLPw(String permission, PackageParser.Package pkg) { - BasePermission bp = mSettings.mPermissions.get(permission); - if (bp == null) { - throw new SecurityException("Missing " + permission + " permission"); - } - - SettingBase sb = (SettingBase) pkg.mExtras; - PermissionsState permissionsState = sb.getPermissionsState(); - - if (permissionsState.grantInstallPermission(bp) != - PermissionsState.PERMISSION_OPERATION_FAILURE) { - scheduleWriteSettingsLocked(); - } - } - @Override public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) { mContext.enforceCallingOrSelfPermission( @@ -14764,6 +14769,7 @@ public class PackageManagerService extends IPackageManager.Stub { pw.println(" version: print database version info"); pw.println(" write: write current settings now"); pw.println(" installs: details about install sessions"); + pw.println(" check-permission []: does pkg hold perm?"); pw.println(" : info about given package"); return; } else if ("--checkin".equals(opt)) { @@ -14785,6 +14791,31 @@ public class PackageManagerService extends IPackageManager.Stub { // When dumping a single package, we always dump all of its // filter information since the amount of data will be reasonable. dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS); + } else if ("check-permission".equals(cmd)) { + if (opti >= args.length) { + pw.println("Error: check-permission missing permission argument"); + return; + } + String perm = args[opti]; + opti++; + if (opti >= args.length) { + pw.println("Error: check-permission missing package argument"); + return; + } + String pkg = args[opti]; + opti++; + int user = UserHandle.getUserId(Binder.getCallingUid()); + if (opti < args.length) { + try { + user = Integer.parseInt(args[opti]); + } catch (NumberFormatException e) { + pw.println("Error: check-permission user argument is not a number: " + + args[opti]); + return; + } + } + pw.println(checkPermission(perm, pkg, user)); + return; } else if ("l".equals(cmd) || "libraries".equals(cmd)) { dumpState.setDump(DumpState.DUMP_LIBS); } else if ("f".equals(cmd) || "features".equals(cmd)) { diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 00d0fe1..ffb6104 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -3949,7 +3949,7 @@ final class Settings { void dumpPackageLPr(PrintWriter pw, String prefix, String checkinTag, ArraySet permissionNames, PackageSetting ps, SimpleDateFormat sdf, - Date date, List users) { + Date date, List users, boolean dumpAll) { if (checkinTag != null) { pw.print(checkinTag); pw.print(","); @@ -4160,7 +4160,21 @@ final class Settings { } } - if (ps.sharedUser == null || permissionNames != null) { + if ((permissionNames != null || dumpAll) && ps.pkg.requestedPermissions != null + && ps.pkg.requestedPermissions.size() > 0) { + final ArrayList perms = ps.pkg.requestedPermissions; + pw.print(prefix); pw.println(" requested permissions:"); + for (int i=0; i 0 && permissionNames == null) { + if (mRenamedPackages.size() > 0 && permissionNames == null) { for (final Map.Entry e : mRenamedPackages.entrySet()) { if (packageName != null && !packageName.equals(e.getKey()) && !packageName.equals(e.getValue())) { @@ -4276,7 +4291,7 @@ final class Settings { printedSomething = true; } dumpPackageLPr(pw, " ", checkin ? "dis" : null, permissionNames, ps, sdf, date, - users); + users, packageName != null); } } } @@ -4361,7 +4376,8 @@ final class Settings { if (!ArrayUtils.isEmpty(gids) || !permissions.isEmpty()) { pw.print(prefix); pw.print("User "); pw.print(userId); pw.println(": "); dumpGidsLPr(pw, prefix + " ", gids); - dumpRuntimePermissionsLPr(pw, prefix + " ", permissionNames, permissions); + dumpRuntimePermissionsLPr(pw, prefix + " ", permissionNames, permissions, + packageName != null); } } } else { @@ -4407,8 +4423,8 @@ final class Settings { } void dumpRuntimePermissionsLPr(PrintWriter pw, String prefix, ArraySet permissionNames, - List permissionStates) { - if (!permissionStates.isEmpty()) { + List permissionStates, boolean dumpAll) { + if (!permissionStates.isEmpty() || dumpAll) { pw.print(prefix); pw.println("runtime permissions:"); for (PermissionState permissionState : permissionStates) { if (permissionNames != null -- cgit v1.1