CVE-2025-48560 AI-generated analysis
platform/frameworks/base, services/accessibility (AbstractAccessibilityServiceConnection)
Moves the ACCESSIBILITY_MOTION_EVENT_OBSERVING permission check in AbstractAccessibilityServiceConnection out of the property-setting code that ran under a cleared Binder identity, and into the service-info update method before Binder.clearCallingIdentity(). The check is now evaluated against the calling accessibility service instead of system_server, and requested observed motion event sources are reset to 0 when the caller lacks the permission.
Root cause
In AbstractAccessibilityServiceConnection.java, the code that copies info.getObservedMotionEventSources() into mObservedMotionEventSources was guarded by mContext.checkCallingOrSelfPermission(ACCESSIBILITY_MOTION_EVENT_OBSERVING), gated on Flags.motionEventObserving(). Per the commit message, this check ran inside a Binder clear-identity call, so it used the permissions of system_server instead of those of the calling AccessibilityService.
How the fix works
- AbstractAccessibilityServiceConnection.java, property-setting code (hunk at about line 405 on 15 and line 420 on 16): the flag-gated checkCallingOrSelfPermission block is removed and replaced by an unconditional mObservedMotionEventSources = info.getObservedMotionEventSources();.
- Same file, in the service-info update method (the one that throws 'Cannot update service info: size is larger than safe parcelable limits.'): a new check runs before Binder.clearCallingIdentity(). If info.getObservedMotionEventSources() != 0 and mContext.checkCallingPermission(ACCESSIBILITY_MOTION_EVENT_OBSERVING) != PERMISSION_GRANTED, it logs via Slog.e and calls info.setObservedMotionEventSources(0).
- The new check uses checkCallingPermission instead of checkCallingOrSelfPermission. A static import of ACCESSIBILITY_MOTION_EVENT_OBSERVING is added.
Completeness
- Covers the service-info update entry point, where the new check runs before the identity is cleared.
- The property-setting code no longer performs any permission check itself. Any other path that supplies an AccessibilityServiceInfo with non-zero observed motion event sources to that code is not covered by the new check. The material does not show whether such paths exist.
- The removed code was gated on android.view.accessibility.Flags.motionEventObserving(). The replacement assignment is unconditional, so the flag no longer gates the copy into mObservedMotionEventSources.
- No change to how mObservedMotionEventSources is consumed downstream. Only the setter side is changed.
Behavior changes
- When a caller without ACCESSIBILITY_MOTION_EVENT_OBSERVING passes non-zero observed motion event sources in a service-info update, the sources are now reset to 0 and a Slog.e message is logged. No exception or error code is returned to the caller.
- Observed motion event sources are copied from the info regardless of the motionEventObserving flag state.
Per major
- Android 14: Not affected: the bulletin does not list Android 14 (7/8 lines of the patched region present at android-security-14.0.0_r29).
- Android 15: Same fix: commit 580118ec5b41 in android-security-15.0.0_r10 (cherry-pick of 01bfef47f3b1, Change-Id If64838388fa31bdc9abb0896d4011bfef8501a7c). 7/8 lines of the patched region present at android-security-15.0.0_r17.
- Android 16: Same fix: commit ff8b0d46a53a in android-security-16.0.0_r1. The diff is identical, with hunks offset by about 15 lines. 7/8 lines of the patched region present at android-security-16.0.0_r8.
- Android 17: Not affected: the bulletin does not list Android 17 (7/8 lines of the patched region present at android-security-17.0.0_r1).
Unknowns
- The exact names of the enclosing methods and whether the update method calls the property-setting code; the diff hunks do not show this.
- Whether other paths into the property-setting code (for example, initial bind) can supply non-zero observed motion event sources.
- What data a service without the permission could observe before the fix; the consumer side is not in the material.