CVE-2025-0098 AI-generated analysis
platform/frameworks/base, WindowManager (services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java, task fragment / activity embedding organizer)
Hardens TaskFragmentOrganizerController so that a real activity token is handed to a task fragment organizer only when both the pid and the uid of the activity match the organizer, and rejects organizer registration from a pid <= 0 (the commit message says a one-way binder call let a malicious app appear as pid 0).
Root cause
In TaskFragmentOrganizerController.java, prepareActivityReparentedToTask passed the activity's real IBinder token (activity.token) to the organizer client based only on activity.getPid() == mOrganizerPid. Otherwise it created a "TemporaryActivityToken" placeholder. The organizer pid is stored when TaskFragmentOrganizerState(organizer, pid, uid, isSystemOrganizer) is created at registration, and registration did not validate it. Per the commit message, a malicious app could register the organizer via a one-way binder call so that it appeared to run on pid 0. Presumably an activity of another process with a matching (0) pid would then pass the pid-only check and its real token would be delivered to the organizer. The material does not show the exact activity state. The same pid-only check guarded the nextFillTaskActivity token passed via change.setOtherActivityToken (under Flags.fixPipRestoreToOverlay()).
How the fix works
- services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java : prepareActivityReparentedToTask: the condition for passing activity.token is tightened from `activity.getPid() == mOrganizerPid` to `activity.getPid() == mOrganizerPid && activity.getUid() == mOrganizerUid`. Otherwise the temporary token path is used as before (new Binder("TemporaryActivityToken") stored in mTemporaryActivityTokens with a timeout).
- Same function, the nextFillTaskActivity branch: `change.setOtherActivityToken(nextFillTaskActivity.token)` now also requires `nextFillTaskActivity.getUid() == mOrganizerUid`, in addition to the pid match and Flags.fixPipRestoreToOverlay().
- Same file, organizer registration (the code that creates TaskFragmentOrganizerState with (organizer, pid, uid, isSystemOrganizer), after the 'Replacing existing organizer currently unsupported' check): adds `if (pid <= 0) throw new IllegalStateException("Cannot register from invalid pid: " + pid)`, so an organizer can no longer be registered with pid 0.
- Single commit (9515a9448c52), cherry-picked twice from internal changes; Merged-In/Change-Id I51378c7d2da06fb83670abd082a089cfd82d699d.
Completeness
- Covers both places in prepareActivityReparentedToTask where a real activity token (activity.token and nextFillTaskActivity.token) is exposed to the organizer, and also blocks registration with pid 0.
- The uid check adds a second condition: even if a pid matched, the uid must also match the organizer.
- The pid validation is only in the registration path shown in the diff. The material does not show whether other registration entry points share this code.
- Other uses of mOrganizerPid in the file (if any) are not shown in the material and are not modified by the diff.
Behavior changes
- Registering a task fragment organizer with a pid <= 0 now throws IllegalStateException("Cannot register from invalid pid: ...") instead of succeeding.
- An activity whose pid matches the organizer pid but whose uid differs now gets a temporary token (reparent via WindowContainerTransaction) instead of the real activity token. Same-process organizers whose pid and uid both match still get the real token.
Per major
- Android 14: not affected per the bulletin (not listed). At android-security-14.0.0_r29 only 3/8 lines of the patched region are present, so the code differs there. The material does not show whether an equivalent change was applied.
- Android 15: same fix: commit 9515a9448c52 in android-security-15.0.0_r5 (resolved by bug_id). At android-security-15.0.0_r17 the code context shows the combined pid && uid check in prepareActivityReparentedToTask (6/8 region lines present).
- Android 16: not affected per the bulletin (not listed). At android-security-16.0.0_r8 5/8 lines of the patched region are present.
- Android 17: not affected per the bulletin (not listed). At android-security-17.0.0_r1 5/8 lines of the patched region are present.
Unknowns
- The exact registration method name and how `pid`/`uid` are obtained there (the diff hunk shows only the code around the TaskFragmentOrganizerState creation).
- Which activity state causes activity.getPid() to match a pid-0 organizer.
- Which inner class holds prepareActivityReparentedToTask.
- Whether Android 14/16/17 contain this fix or an equivalent; the material gives only partial line-match counts, and the bulletin lists only 15/15-next.