CVE-2024-34738 AI-generated analysis
platform/frameworks/base, AppOps (services/core/java/com/android/server/appop/AppOpsService.java)
AppOpsService now filters restricted-read app ops out of collectOps() results unless the caller holds GET_APP_OPS_STATS, and verifyIncomingOp() accepts any of MANAGE_APPOPS, GET_APP_OPS_STATS or MANAGE_APP_OPS_MODES instead of only MANAGE_APPOPS for restricted ops.
Root cause
Ops flagged restrictRead (AppOpsManager.opRestrictsRead) were checked in verifyIncomingOp(), which enforced MANAGE_APPOPS for a restricted op. The result builder collectOps(Ops pkgOps, int[] ops) did no permission check at all. When ops == null it added every Op of the package, and when an ops array was given it added every matching Op. So restricted-read op entries could appear in the results it built regardless of the caller's permissions. Separately, verifyIncomingOp only accepted MANAGE_APPOPS and rejected other privileged appops permission holders.
How the fix works
- AppOpsService.java:collectOps: computes shouldReturnRestrictedAppOps = mContext.checkPermission(GET_APP_OPS_STATS, Binder.getCallingPid(), Binder.getCallingUid()) == PERMISSION_GRANTED once per call.
- AppOpsService.java:collectOps (ops == null branch): skips any Op where opRestrictsRead(curOp.op) is true and the caller lacks GET_APP_OPS_STATS, before getOpEntryForResult is called.
- AppOpsService.java:collectOps (explicit ops[] branch): applies the same skip to each non-null Op found in pkgOps, before resOps is allocated or appended.
- AppOpsService.java:verifyIncomingOp: for opRestrictsRead(op), replaces enforcePermission(MANAGE_APPOPS) with a check that the caller holds at least one of MANAGE_APPOPS, GET_APP_OPS_STATS or MANAGE_APP_OPS_MODES. Otherwise it throws a SecurityException listing the three permissions.
- AppOpInfo.java (restrictRead javadoc) and AppOpsManager.java:opRestrictsRead javadoc: comment-only changes from 'manage appops permission' to 'privileged appops permission'.
Completeness
- Covers both branches of collectOps (all ops and explicit op list), so every result path that goes through collectOps filters restricted ops for callers without GET_APP_OPS_STATS.
- The two checks are not symmetric. The collectOps filter keys only on GET_APP_OPS_STATS, while verifyIncomingOp also accepts MANAGE_APPOPS or MANAGE_APP_OPS_MODES. A caller holding only MANAGE_APPOPS or MANAGE_APP_OPS_MODES passes verifyIncomingOp for a restricted op but still has that op filtered out of collectOps results.
- The commit message mentions READ and WRITE access issues, but the diff only changes read-side paths (collectOps, verifyIncomingOp). No write/set path is modified in this commit.
- The material does not show the callers of collectOps or any other code paths that build OpEntry results for restricted ops, so coverage of those paths cannot be judged.
Behavior changes
- Callers without GET_APP_OPS_STATS no longer see restricted-read ops in results built by collectOps. Such entries are silently left out instead of causing an error.
- verifyIncomingOp becomes more permissive for restricted ops: holders of GET_APP_OPS_STATS or MANAGE_APP_OPS_MODES are accepted in addition to MANAGE_APPOPS.
- The SecurityException message from verifyIncomingOp changes to list the three accepted permissions.
- Callers holding only MANAGE_APPOPS (without GET_APP_OPS_STATS) now get restricted ops filtered out of collectOps results, where previously those ops were returned.
Per major
- Android 14: same fix: commit 21d764807b3d in android-security-14.0.0_r11 (cherry-pick of e31c33ea3586). At android-security-14.0.0_r29 the collectOps filter is present, with an additional NUM_ATTRIBUTED_OP_ENTRY_THRESHOLD limit interleaved (6/8 patched lines present).
- Android 15: not affected (not listed by the bulletin); at android-security-15.0.0_r17, 5/8 lines of the patched region are present.
- Android 16: not affected (not listed by the bulletin); at android-security-16.0.0_r8, 5/8 lines of the patched region are present.
- Android 17: not affected (not listed by the bulletin); at android-security-17.0.0_r1, 5/8 lines of the patched region are present.
Unknowns
- Which Binder entry points call collectOps, and whether they call verifyIncomingOp first (not shown in the material).
- What the 'WRITE operation access' part of the commit message refers to. No write-path change appears in this diff, so whether a companion commit exists is unknown.
- Which specific ops have restrictRead set in this release.
- Whether the Android 13 fix (13 is listed as affected by the bulletin) is identical, and whether the dependencies exist on 13. No 13 commit is in the material.