From 826767b9f1f1ff93420df93f3c1ca67ff7f4e455 Mon Sep 17 00:00:00 2001 From: Nate Myren Date: Fri, 15 Apr 2022 15:18:15 -0700 Subject: [PATCH] Add command to allow setting of some permission flags from shell Add the "pm set/clear-permission-flags" adb commands, which will allow a developer to set the USER_SET, USER_FIXED, REVIEW_REQUIRED, REVOKED_COMPAT, and REVOKE_WHEN_REQUESTED flags via adb. Test: manual Fixes: 229321394 Change-Id: I6a85466ce25ce24eececde936214cfc033fafac0 --- .../server/pm/PackageManagerShellCommand.java | 72 +++++++++++++++++++ .../PermissionManagerServiceImpl.java | 6 +- 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index d6ab78bd27ea5..7b06593324121 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -17,6 +17,11 @@ package com.android.server.pm; import static android.content.pm.PackageInstaller.LOCATION_DATA_APP; +import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; +import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT; +import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED; +import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED; +import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET; import android.accounts.IAccountManager; import android.annotation.NonNull; @@ -92,6 +97,7 @@ import android.system.ErrnoException; import android.system.Os; import android.text.TextUtils; import android.text.format.DateUtils; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.IntArray; import android.util.PrintWriterPrinter; @@ -150,6 +156,17 @@ class PackageManagerShellCommand extends ShellCommand { "--multi-package" ); private static final Set UNSUPPORTED_SESSION_CREATE_OPTS = Collections.emptySet(); + private static final Map SUPPORTED_PERMISSION_FLAGS = new ArrayMap<>(); + private static final List SUPPORTED_PERMISSION_FLAGS_LIST; + static { + SUPPORTED_PERMISSION_FLAGS.put("user-set", FLAG_PERMISSION_USER_SET); + SUPPORTED_PERMISSION_FLAGS.put("user-fixed", FLAG_PERMISSION_USER_FIXED); + SUPPORTED_PERMISSION_FLAGS.put("revoked-compat", FLAG_PERMISSION_REVOKED_COMPAT); + SUPPORTED_PERMISSION_FLAGS.put("review-required", FLAG_PERMISSION_REVIEW_REQUIRED); + SUPPORTED_PERMISSION_FLAGS.put("revoke-when-requested", + FLAG_PERMISSION_REVOKE_WHEN_REQUESTED); + SUPPORTED_PERMISSION_FLAGS_LIST = new ArrayList<>(SUPPORTED_PERMISSION_FLAGS.keySet()); + } final IPackageManager mInterface; final LegacyPermissionManagerInternal mLegacyPermissionManager; @@ -276,6 +293,10 @@ class PackageManagerShellCommand extends ShellCommand { return runGrantRevokePermission(false); case "reset-permissions": return runResetPermissions(); + case "set-permission-flags": + return setOrClearPermissionFlags(true); + case "clear-permission-flags": + return setOrClearPermissionFlags(false); case "set-permission-enforced": return runSetPermissionEnforced(); case "get-privapp-permissions": @@ -2500,6 +2521,50 @@ class PackageManagerShellCommand extends ShellCommand { return 0; } + private int setOrClearPermissionFlags(boolean setFlags) { + int userId = UserHandle.USER_SYSTEM; + + String opt; + while ((opt = getNextOption()) != null) { + if (opt.equals("--user")) { + userId = UserHandle.parseUserArg(getNextArgRequired()); + } + } + + String pkg = getNextArg(); + if (pkg == null) { + getErrPrintWriter().println("Error: no package specified"); + return 1; + } + String perm = getNextArg(); + if (perm == null) { + getErrPrintWriter().println("Error: no permission specified"); + return 1; + } + + int flagMask = 0; + String flagName = getNextArg(); + if (flagName == null) { + getErrPrintWriter().println("Error: no permission flags specified"); + return 1; + } + while (flagName != null) { + if (!SUPPORTED_PERMISSION_FLAGS.containsKey(flagName)) { + getErrPrintWriter().println("Error: specified flag " + flagName + " is not one of " + + SUPPORTED_PERMISSION_FLAGS_LIST); + return 1; + } + flagMask |= SUPPORTED_PERMISSION_FLAGS.get(flagName); + flagName = getNextArg(); + } + + final UserHandle translatedUser = UserHandle.of(translateUserId(userId, + UserHandle.USER_NULL, "runGrantRevokePermission")); + int flagSet = setFlags ? flagMask : 0; + mPermissionManager.updatePermissionFlags(pkg, perm, flagMask, flagSet, translatedUser); + return 0; + } + private int runSetPermissionEnforced() throws RemoteException { final String permission = getNextArg(); if (permission == null) { @@ -3997,6 +4062,13 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" must be declared as used in the app's manifest, be runtime permissions"); pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1."); pw.println(""); + pw.println(" set-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]"); + pw.println(" clear-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]"); + pw.println(" These commands either set or clear permission flags on apps. The permissions"); + pw.println(" must be declared as used in the app's manifest, be runtime permissions"); + pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1."); + pw.println(" The flags must be one or more of " + SUPPORTED_PERMISSION_FLAGS_LIST); + pw.println(""); pw.println(" reset-permissions"); pw.println(" Revert all runtime permissions to their default state."); pw.println(""); diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java index c524fb7ae9e57..df7e898f66b4b 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java @@ -761,8 +761,10 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT; flagValues &= ~FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT; flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION; - // REVIEW_REQUIRED can only be set by non-system apps for for POST_NOTIFICATIONS - if (!POST_NOTIFICATIONS.equals(permName)) { + // REVIEW_REQUIRED can only be set by non-system apps for POST_NOTIFICATIONS, or by the + // shell or root UID. + if (!POST_NOTIFICATIONS.equals(permName) && callingUid != Process.SHELL_UID + && callingUid != Process.ROOT_UID) { flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; } }