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

Commit 955e7807 authored by Hao Ke's avatar Hao Ke
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
Change-Id: I09008b365e36b2c20c9a1fe5a1d52699ddb17d35
parent 1e2886ce
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -88,7 +88,7 @@ class AppOpInfo {


    /**
    /**
     * This specifies whether each option is only allowed to be read
     * 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;
    public final boolean restrictRead;


+1 −1
Original line number Original line Diff line number Diff line
@@ -3269,7 +3269,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
     * @hide
     */
     */
    public static boolean opRestrictsRead(int op) {
    public static boolean opRestrictsRead(int op) {
+26 −5
Original line number Original line Diff line number Diff line
@@ -1563,10 +1563,17 @@ public class AppOpsService extends IAppOpsService.Stub {
    private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops,
    private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops,
            String persistentDeviceId) {
            String persistentDeviceId) {
        ArrayList<AppOpsManager.OpEntry> resOps = null;
        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) {
        if (ops == null) {
            resOps = new ArrayList<>();
            resOps = new ArrayList<>();
            for (int j = 0; j < pkgOps.size(); j++) {
            for (int j = 0; j < pkgOps.size(); j++) {
                Op curOp = pkgOps.valueAt(j);
                Op curOp = pkgOps.valueAt(j);
                if (opRestrictsRead(curOp.op) && !shouldReturnRestrictedAppOps) {
                    continue;
                }
                resOps.add(getOpEntryForResult(curOp, persistentDeviceId));
                resOps.add(getOpEntryForResult(curOp, persistentDeviceId));
            }
            }
        } else {
        } else {
@@ -1576,6 +1583,9 @@ public class AppOpsService extends IAppOpsService.Stub {
                    if (resOps == null) {
                    if (resOps == null) {
                        resOps = new ArrayList<>();
                        resOps = new ArrayList<>();
                    }
                    }
                    if (opRestrictsRead(curOp.op) && !shouldReturnRestrictedAppOps) {
                        continue;
                    }
                    resOps.add(getOpEntryForResult(curOp, persistentDeviceId));
                    resOps.add(getOpEntryForResult(curOp, persistentDeviceId));
                }
                }
            }
            }
@@ -4242,10 +4252,21 @@ public class AppOpsService extends IAppOpsService.Stub {


    private void verifyIncomingOp(int op) {
    private void verifyIncomingOp(int op) {
        if (op >= 0 && op < AppOpsManager._NUM_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)) {
            if (opRestrictsRead(op)) {
                mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS,
                if (!(mContext.checkPermission(Manifest.permission.MANAGE_APPOPS,
                        Binder.getCallingPid(), Binder.getCallingUid(), "verifyIncomingOp");
                        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;
            return;
        }
        }