diff options
author | Dianne Hackborn <hackbod@google.com> | 2015-08-13 18:25:20 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2015-08-13 18:25:20 -0700 |
commit | 9f5b0a27350df984fb4a98b9658e89390ed60573 (patch) | |
tree | c3d3757da560d8fae28edb92964ead0c891445e8 | |
parent | ff9912d594bc5cdc10a4a224b9a2296bac50851b (diff) | |
download | frameworks_base-9f5b0a27350df984fb4a98b9658e89390ed60573.zip frameworks_base-9f5b0a27350df984fb4a98b9658e89390ed60573.tar.gz frameworks_base-9f5b0a27350df984fb4a98b9658e89390ed60573.tar.bz2 |
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
4 files changed, 82 insertions, 28 deletions
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 <permission> <package> [<user>]: does pkg hold perm?"); pw.println(" <package.name>: 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<String> permissionNames, PackageSetting ps, SimpleDateFormat sdf, - Date date, List<UserInfo> users) { + Date date, List<UserInfo> 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<String> perms = ps.pkg.requestedPermissions; + pw.print(prefix); pw.println(" requested permissions:"); + for (int i=0; i<perms.size(); i++) { + String perm = perms.get(i); + if (permissionNames != null + && !permissionNames.contains(perm)) { + continue; + } + pw.print(prefix); pw.print(" "); pw.println(perm); + } + } + + if (ps.sharedUser == null || permissionNames != null || dumpAll) { PermissionsState permissionsState = ps.getPermissionsState(); dumpInstallPermissionsLPr(pw, prefix + " ", permissionNames, permissionsState); } @@ -4187,7 +4201,7 @@ final class Settings { PermissionsState permissionsState = ps.getPermissionsState(); dumpGidsLPr(pw, prefix + " ", permissionsState.computeGids(user.id)); dumpRuntimePermissionsLPr(pw, prefix + " ", permissionNames, permissionsState - .getRuntimePermissionStates(user.id)); + .getRuntimePermissionStates(user.id), dumpAll); } if (permissionNames == null) { @@ -4235,11 +4249,12 @@ final class Settings { pw.println("Packages:"); printedSomething = true; } - dumpPackageLPr(pw, " ", checkin ? "pkg" : null, permissionNames, ps, sdf, date, users); + dumpPackageLPr(pw, " ", checkin ? "pkg" : null, permissionNames, ps, sdf, date, users, + packageName != null); } printedSomething = false; - if (!checkin && mRenamedPackages.size() > 0 && permissionNames == null) { + if (mRenamedPackages.size() > 0 && permissionNames == null) { for (final Map.Entry<String, String> 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<String> permissionNames, - List<PermissionState> permissionStates) { - if (!permissionStates.isEmpty()) { + List<PermissionState> permissionStates, boolean dumpAll) { + if (!permissionStates.isEmpty() || dumpAll) { pw.print(prefix); pw.println("runtime permissions:"); for (PermissionState permissionState : permissionStates) { if (permissionNames != null diff --git a/tests/VoiceInteraction/AndroidManifest.xml b/tests/VoiceInteraction/AndroidManifest.xml index 36d5d98..fe17c6e 100644 --- a/tests/VoiceInteraction/AndroidManifest.xml +++ b/tests/VoiceInteraction/AndroidManifest.xml @@ -2,6 +2,7 @@ package="com.android.test.voiceinteraction"> <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" /> + <uses-permission android:name="android.permission.READ_LOGS" /> <application> <activity android:name="VoiceInteractionMain" android:label="Voice Interaction" |