CVE-2024-31322 AI-generated analysis
platform/frameworks/base, services/accessibility (AccessibilityManagerService)
AccessibilityManagerService.updateServicesLocked now removes components that are no longer installed from the user's enabled accessibility services list and touch-exploration-granted list and persists both settings, so a service that disappears after a service update does not stay enabled.
Root cause
In services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java, updateServicesLocked(AccessibilityUserState) iterated userState.mInstalledServices to manage service connections, but never reconciled userState.mEnabledServices or userState.mTouchExplorationGrantedServices against the installed set. When a service update removed the accessibility service component (test name: testUpdateServiceWithoutIntent_disablesService), its ComponentName stayed in both in-memory lists and in the persisted Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES and TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES values, so the enabled and granted state survived the removal of the service. The bulletin rates this as a High EoP.
How the fix works
- AccessibilityManagerService.java:updateServicesLocked: mTempComponentNameSet is cleared before the installed-services loop. At the top of the loop, each installed service's ComponentName (ComponentName.unflattenFromString(installedService.getId())) is added to it before any 'continue', so services that are not direct-boot-aware, still binding or crashed are still counted as installed.
- AccessibilityManagerService.java:updateServicesLocked: after mActivityTaskManagerService.setAccessibilityServiceUids(mTempIntArray), userState.mEnabledServices.removeIf(comp -> !mTempComponentNameSet.contains(comp)) || userState.mTouchExplorationGrantedServices.removeIf(...) drops components that are not installed.
- If anyServiceRemoved is true, persistComponentNamesToSettingLocked is called for Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES with userState.mEnabledServices, and for Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES with userState.mTouchExplorationGrantedServices, both for userState.mUserId. mTempComponentNameSet is then cleared, and updateAccessibilityEnabledSettingLocked(userState) runs as before.
Completeness
- Covers both in-memory lists (mEnabledServices and mTouchExplorationGrantedServices) and their persisted Settings.Secure values, for the user whose state is being updated.
- The two removeIf calls are joined with '||', which short-circuits. When mEnabledServices.removeIf returns true, mTouchExplorationGrantedServices.removeIf does not run in that pass, so the touch-exploration-granted list is persisted without pruning. That list is pruned only in a pass where nothing is removed from mEnabledServices, for example a later updateServicesLocked pass.
- Pruning happens only when updateServicesLocked runs. The diff does not touch other code that reads these lists or settings.
- The material shows only the Android 14 frameworks/base commit. The bulletin also lists 12, 12L and 13 as affected.
Behavior changes
- Enabled accessibility services whose component is no longer in userState.mInstalledServices are now removed from the enabled list (and, subject to the '||' short-circuit, from the touch-exploration-granted list), and both Settings.Secure values are rewritten.
- Settings are written from within updateServicesLocked through persistComponentNamesToSettingLocked, and only when something was removed.
Per major
- Android 14: same fix: commit c1bc907a649a ([RESTRICT AUTOMERGE] cherry-pick of f6192d3a7752, Change-Id Ia86857d58ebab925ec6e55f9e5fa64e265326ec0) in android-security-14.0.0_r9; 8/8 patched lines present at android-security-14.0.0_r29.
- Android 15: not affected (per the bulletin); the patched region is fully present (8/8 lines) at android-security-15.0.0_r17.
- Android 16: not affected (per the bulletin); the patched region is fully present (8/8 lines) at android-security-16.0.0_r8.
- Android 17: not affected (per the bulletin); 6/8 patched lines present at android-security-17.0.0_r1; the material does not show the difference.
Unknowns
- Commits for Android 12, 12L and 13 (listed as affected by the bulletin) are not in the material.
- What differs in the Android 17 region, where only 6/8 patched lines match.
- The body of persistComponentNamesToSettingLocked (for example, how it handles empty sets and calling identity).
- The exact update scenario and its consequence, beyond the commit title and test name.