summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2015-08-13 18:25:20 -0700
committerDianne Hackborn <hackbod@google.com>2015-08-13 18:25:20 -0700
commit9f5b0a27350df984fb4a98b9658e89390ed60573 (patch)
treec3d3757da560d8fae28edb92964ead0c891445e8
parentff9912d594bc5cdc10a4a224b9a2296bac50851b (diff)
downloadframeworks_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
-rw-r--r--services/core/java/com/android/server/pm/BasePermission.java6
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java69
-rw-r--r--services/core/java/com/android/server/pm/Settings.java34
-rw-r--r--tests/VoiceInteraction/AndroidManifest.xml1
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"