Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 03d9c145 authored by Hao Ke's avatar Hao Ke Committed by Cherrypicker Worker
Browse files

Fix READ/WRITE operation access issues on Restricted appOps.

Problems were identified around read and write access to the restricted appOps, this change includes:

- Filter out restricted appOps status for unprivileged readers.
- Allow additional privileged appOps permission holder reading restricted appOps status.

Bug: 336273802
Bug: 336323279
Test: Local test see b/336273802#comment3
Test: atest AppOpsTest#testRestrictedSettingsOpsRead
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:955e78071ec49139583056e21f612edba6439436)
Merged-In: I09008b365e36b2c20c9a1fe5a1d52699ddb17d35
Change-Id: I09008b365e36b2c20c9a1fe5a1d52699ddb17d35
24D1-dev is based on 24Q2-release. Therefore, we merged this CL to 24D1-dev.
parent 23646b93
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -88,7 +88,7 @@ class AppOpInfo {

    /**
     * This specifies whether each option is only allowed to be read
     * by apps with manage appops permission.
     * by apps with privileged appops permission.
     */
    public final boolean restrictRead;

+1 −1
Original line number Diff line number Diff line
@@ -3268,7 +3268,7 @@ public class AppOpsManager {
    }

    /**
     * Retrieve whether the op can be read by apps with manage appops permission.
     * Retrieve whether the op can be read by apps with privileged appops permission.
     * @hide
     */
    public static boolean opRestrictsRead(int op) {
+26 −5
Original line number Diff line number Diff line
@@ -1561,10 +1561,17 @@ public class AppOpsService extends IAppOpsService.Stub {
    private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops,
            String persistentDeviceId) {
        ArrayList<AppOpsManager.OpEntry> resOps = null;
        boolean shouldReturnRestrictedAppOps = mContext.checkPermission(
                Manifest.permission.GET_APP_OPS_STATS,
                Binder.getCallingPid(), Binder.getCallingUid())
                == PackageManager.PERMISSION_GRANTED;
        if (ops == null) {
            resOps = new ArrayList<>();
            for (int j = 0; j < pkgOps.size(); j++) {
                Op curOp = pkgOps.valueAt(j);
                if (opRestrictsRead(curOp.op) && !shouldReturnRestrictedAppOps) {
                    continue;
                }
                resOps.add(getOpEntryForResult(curOp, persistentDeviceId));
            }
        } else {
@@ -1574,6 +1581,9 @@ public class AppOpsService extends IAppOpsService.Stub {
                    if (resOps == null) {
                        resOps = new ArrayList<>();
                    }
                    if (opRestrictsRead(curOp.op) && !shouldReturnRestrictedAppOps) {
                        continue;
                    }
                    resOps.add(getOpEntryForResult(curOp, persistentDeviceId));
                }
            }
@@ -4226,10 +4236,21 @@ public class AppOpsService extends IAppOpsService.Stub {

    private void verifyIncomingOp(int op) {
        if (op >= 0 && op < AppOpsManager._NUM_OP) {
            // Enforce manage appops permission if it's a restricted read op.
            // Enforce privileged appops permission if it's a restricted read op.
            if (opRestrictsRead(op)) {
                mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS,
                        Binder.getCallingPid(), Binder.getCallingUid(), "verifyIncomingOp");
                if (!(mContext.checkPermission(Manifest.permission.MANAGE_APPOPS,
                        Binder.getCallingPid(), Binder.getCallingUid())
                        == PackageManager.PERMISSION_GRANTED || mContext.checkPermission(
                        Manifest.permission.GET_APP_OPS_STATS,
                        Binder.getCallingPid(), Binder.getCallingUid())
                        == PackageManager.PERMISSION_GRANTED || mContext.checkPermission(
                        Manifest.permission.MANAGE_APP_OPS_MODES,
                        Binder.getCallingPid(), Binder.getCallingUid())
                        == PackageManager.PERMISSION_GRANTED)) {
                    throw new SecurityException("verifyIncomingOp: uid " + Binder.getCallingUid()
                            + " does not have any of {MANAGE_APPOPS, GET_APP_OPS_STATS, "
                            + "MANAGE_APP_OPS_MODES}");
                }
            }
            return;
        }