CVE-2024-23708 AI-generated analysis
platform/frameworks/base, system_server: NotificationManagerService toast queue and ClipboardService clipboard-access toast
NotificationManagerService now puts system-package toasts ahead of pending non-system toasts in mToastQueue (behind the toast currently on screen and after any queued system toasts) instead of adding them at the end, and ClipboardService's "pasted from clipboard" warning toast changes from LENGTH_SHORT to LENGTH_LONG, so apps can no longer delay system toasts by filling the queue.
Root cause
In NotificationManagerService's toast enqueue path (inside synchronized (mToastQueue)), every new ToastRecord was appended with mToastQueue.add(record) and index = mToastQueue.size() - 1, whatever the value of isSystemToast. Within this block, the only cap on queue entries was the per-package MAX_PACKAGE_TOASTS. A non-system package could queue up to MAX_PACKAGE_TOASTS toasts, and any system toast requested later waited behind all of them. The commit also lengthens the ClipboardService paste warning toast, which used Toast.LENGTH_SHORT.
How the fix works
- services/core/java/com/android/server/notification/NotificationManagerService.java, toast enqueue path (the block under synchronized (mToastQueue) that builds the ToastRecord via getToastRecord): after the record is created, a new local systemToastInsertIdx defaults to mToastQueue.size(). If isSystemToast is true, it is set from the new getInsertIndexForSystemToastLocked(). If the index is less than mToastQueue.size(), the record is inserted there with mToastQueue.add(index, record). Otherwise the old behaviour is kept (append, index = size()-1). The existing 'if (index == 0) showNextToastLocked(false)' logic is unchanged.
- services/core/java/com/android/server/notification/NotificationManagerService.java: the new @GuardedBy("mToastQueue") getInsertIndexForSystemToastLocked() walks mToastQueue. It skips index 0 when mIsCurrentToastShown is true, then returns the index of the first ToastRecord whose isSystemToast is false. If no such record exists, it returns mToastQueue.size(), so the new toast goes after the last system toast.
- services/core/java/com/android/server/clipboard/ClipboardService.java, clipboard-access toast code (the Binder.withCleanCallingIdentity block that builds the R.string.pasted_from_clipboard message): both Toast.makeCustomToastWithIcon and Toast.makeText now use Toast.LENGTH_LONG instead of Toast.LENGTH_SHORT.
- services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java adds two tests. testPrioritizeSystemToasts queues MAX_PACKAGE_TOASTS non-system toasts, then one system toast, and asserts the system toast lands at index 1. testPrioritizeSystemToasts_enqueueAfterExistingSystemToast queues MAX_PACKAGE_TOASTS system toasts, then another system toast, and asserts the new one is last.
Completeness
- Only covers newly enqueued ToastRecords. A toast already in the queue (indexOfToastLocked(pkg, token) >= 0) is updated in place and not moved; this is unchanged behaviour.
- The toast currently on screen is not preempted, because index 0 is skipped when mIsCurrentToastShown is true.
- The per-package MAX_PACKAGE_TOASTS check runs before the insertion logic and applies to system packages too. The fix changes ordering, not capacity.
- Priority depends only on the isSystemToast flag passed into getToastRecord. How that flag is derived is outside the diff.
- Only the ClipboardService toast duration changed.
Behavior changes
- When system and non-system toasts are both queued, system toasts are shown before pending non-system toasts (after the one currently on screen).
- System toasts keep FIFO order among themselves.
- The clipboard 'pasted from clipboard' toast now shows for LENGTH_LONG instead of LENGTH_SHORT.
- Non-system toasts are still appended to the end of the queue. The diff adds no new rejections.
Per major
- Android 14: same fix: commit b9f175fb1f5c (Change-Id I13547f853476bc88d12026c545aba9f857ce8724) in android-security-14.0.0_r8. At android-security-14.0.0_r29, 7/8 lines of the patched region are present, and the code context shows the insertion logic and the LENGTH_LONG clipboard toast.
- Android 15: not affected (not listed by the bulletin); 7/8 lines of the patched region present at android-security-15.0.0_r17.
- Android 16: not affected (not listed by the bulletin); 7/8 lines of the patched region present at android-security-16.0.0_r8.
- Android 17: not affected (not listed by the bulletin); 7/8 lines of the patched region present at android-security-17.0.0_r1.
Unknowns
- How isSystemToast is computed for a caller, and therefore which callers get priority (not in the diff).
- The name of the enclosing ClipboardService method that builds the clipboard-access toast.
- Which commits fix Android 12, 12L and 13.
- Why one line of the eight-line patched region differs at the latest security tags.