CVE-2025-48574 AI-generated analysis
platform/frameworks/base, WindowManager (services/core/java/com/android/server/wm/DisplayPolicy.java)
DisplayPolicy.validateAddingWindowLw now enforces MANAGE_ACTIVITY_TASKS against the explicitly supplied callingPid/callingUid when a window requests PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP, instead of calling ActivityTaskManagerService.enforceTaskPermission(), which reads the Binder calling identity that has already been cleared at that point.
Root cause
In DisplayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid), the branch for attrs.privateFlags containing PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP called the static ActivityTaskManagerService.enforceTaskPermission("DisplayPolicy"). Per the commit message, that helper uses the Binder calling uid/pid, which has been cleared before validateAddingWindowLw() is invoked, so the check did not evaluate the window's real caller. The sibling checks in the same method (PRIVATE_FLAG_TRUSTED_OVERLAY, TYPE_STATUS_BAR, TYPE_NOTIFICATION_SHADE, TYPE_NAVIGATION_BAR) use mContext.enforcePermission(..., callingPid, callingUid, ...) with the passed-in identity; this branch did not.
How the fix works
- services/core/java/com/android/server/wm/DisplayPolicy.java:validateAddingWindowLw: replaces ActivityTaskManagerService.enforceTaskPermission("DisplayPolicy") with mContext.enforcePermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS, callingPid, callingUid, "DisplayPolicy"), so the permission is evaluated against the pid/uid parameters handed to the method rather than the cleared Binder identity. This aligns the branch with the neighbouring PRIVATE_FLAG_TRUSTED_OVERLAY and status-bar type checks in the same method.
- services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java:testPrivateInterceptGlobalDragDropFlagChecksPermission: the test (which spies mWm.mContext) now verifies enforcePermission(eq(MANAGE_ACTIVITY_TASKS), anyInt(), anyInt(), any()) is called, instead of verifying mWm.mAtmService.enforceTaskPermission(any()).
Completeness
- Covers the single PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP check in DisplayPolicy.validateAddingWindowLw; this is the only call site of the flawed static check shown in the material.
- The other permission checks in validateAddingWindowLw (PRIVATE_FLAG_TRUSTED_OVERLAY with INTERNAL_SYSTEM_WINDOW; TYPE_STATUS_BAR, TYPE_NOTIFICATION_SHADE, TYPE_NAVIGATION_BAR with STATUS_BAR_SERVICE) already used mContext.enforcePermission with callingPid/callingUid at android-security-14.0.0_r29 and are unchanged.
- The fix does not change where or how the Binder identity is cleared on the add-window path; it only makes this check use the explicit identity. Whether other checks downstream of the identity clearing rely on Binder.getCallingUid() is not shown in the material.
Behavior changes
- Adding a window whose LayoutParams.privateFlags include PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP now throws a SecurityException from mContext.enforcePermission unless the supplied callingPid/callingUid holds android.permission.MANAGE_ACTIVITY_TASKS; previously the check was evaluated against the (cleared) Binder identity.
- The permission check is now specifically MANAGE_ACTIVITY_TASKS; the exact set of permissions accepted by the former ActivityTaskManagerService.enforceTaskPermission() is not shown in the material, so callers relying on any alternative permission accepted there could now be rejected.
Per major
- Android 14: same fix: platform/frameworks/base 04b124bf59a8 in android-security-14.0.0_r24 (cherry-pick of 467b18585de4); DisplayPolicy.java hunk at line 1009 plus DragDropControllerTests update; the patched code is visible in the android-security-14.0.0_r29 code context (resolver reports 5/7 lines of the patched region present).
- Android 15: same fix: platform/frameworks/base e6e8c87c3c99 in android-security-15.0.0_r12; identical DisplayPolicy.java change (hunk at line 1060) and identical test change; 5/7 lines of the patched region present at android-security-15.0.0_r17.
- Android 16: same fix: platform/frameworks/base 1cfd8237b5a8 in android-security-16.0.0_r3; identical DisplayPolicy.java change (hunk at line 1071, followed by 'final String systemUiPermission =' instead of 'switch (attrs.type)') and identical test change; 5/7 lines of the patched region present at android-security-16.0.0_r8.
- Android 17: not affected per the bulletin; 5/7 lines of the patched region are present at android-security-17.0.0_r1. No separate fix commit for 17 is shown in the material.
Unknowns
- Where on the add-window path the Binder calling identity is cleared and how callingPid/callingUid are obtained before validateAddingWindowLw is invoked (not shown).
- The exact permissions accepted by the former ActivityTaskManagerService.enforceTaskPermission(), so whether the new MANAGE_ACTIVITY_TASKS-only check narrows legitimate callers cannot be determined from the material.
- What privileges PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP confers at runtime (the material only shows testPrivateInterceptGlobalDragDropFlagBehaviour, which exercises drag-start delivery to invisible windows and drop handling).
- Which 2 of the 7 patched-region lines are reported missing at the latest security tags.