CVE-2024-0027 AI-generated analysis
platform/frameworks/base, NotificationManagerService / SnoozeHelper (services/core/java/com/android/server/notification)
SnoozeHelper.canSnooze now also counts the two persisted snoozed-notification maps against CONCURRENT_SNOOZE_LIMIT, and repostGroupSummary removes the group summary key from those persisted maps when the in-memory record is removed, bounding the snoozed-notification state that is serialized to disk.
Root cause
SnoozeHelper keeps three maps: in-memory mSnoozedNotifications (key -> NotificationRecord) and two persisted maps, mPersistedSnoozedNotifications (key -> time) and mPersistedSnoozedNotificationsWithContext (key -> context id), which survive reboots via XML. canSnooze(int) only compared mSnoozedNotifications.size() + numberToSnooze against CONCURRENT_SNOOZE_LIMIT, so the persisted maps were never bounded. In addition, repostGroupSummary removed the group summary record from mSnoozedNotifications but left its entry in both persisted maps, so persisted entries could accumulate independently of the in-memory count. Per the commit message, serializing a huge number of snoozed notifications caused a boot loop.
How the fix works
- services/core/java/com/android/server/notification/SnoozeHelper.java:canSnooze - the limit check now also returns false when mPersistedSnoozedNotifications.size() + mPersistedSnoozedNotificationsWithContext.size() + numberToSnooze exceeds CONCURRENT_SNOOZE_LIMIT, under mLock, in addition to the existing in-memory check.
- services/core/java/com/android/server/notification/SnoozeHelper.java:repostGroupSummary - after mSnoozedNotifications.remove(groupSummaryKey), the fix computes getTrimmedString(groupSummaryKey) and removes that trimmed key from mPersistedSnoozedNotificationsWithContext and mPersistedSnoozedNotifications, so the persisted state tracks the in-memory removal.
- services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java - adds testSnoozeLimit_maximumPersisted (loads CONCURRENT_SNOOZE_LIMIT persisted entries via readXml, asserts canSnooze(1) is false while isSnoozed is false), extends repostGroupSummary_repostsSummary and adds snoozeWithContext_repostGroupSummary_removesPersisted to assert the persisted entry for the summary is cleared.
Completeness
- Covers: the persisted maps are now counted in canSnooze, and the group-summary repost path cleans up both persisted maps.
- The commit message lists a third item, 'Prevent unpriviledged API calls that allow 3P apps to snooze notifications with context/criterion', and a NotificationManagerServiceTest test target, but the diff touches only SnoozeHelper.java and SnoozeHelperTest.java; that NotificationManagerService change is not in this commit as shown, so it is either a separate change or not part of this cherry-pick.
- The persisted-map check in canSnooze uses the combined size of both persisted maps against the same single CONCURRENT_SNOOZE_LIMIT; the in-memory and persisted checks are independent, so either one reaching the limit blocks new snoozes.
- Only repostGroupSummary gained persisted-map cleanup in this diff; other removal paths in SnoozeHelper are not shown in the material, so whether they already clear the persisted maps cannot be judged from what is provided.
Behavior changes
- canSnooze returns false (new snoozes refused) when the persisted snoozed-notification entries, including ones loaded from XML after a reboot, reach CONCURRENT_SNOOZE_LIMIT, even if the in-memory map is small.
- After repostGroupSummary, getSnoozeTimeForUnpostedNotification returns 0 and getSnoozeContextForUnpostedNotification returns null for the reposted summary key, where previously stale persisted values remained.
Per major
- Android 14: same fix: commit a8fb9fe93efd in android-security-14.0.0_r5 (cherry-pick of 965ff2d3c548, Change-Id I3571fa9207b778def652130d3ca840183a9a8414); at android-security-14.0.0_r29 the patched region is present (7/8 lines matched).
- Android 15: not affected per the bulletin; the patched region is present at android-security-15.0.0_r17 (7/8 lines).
- Android 16: not affected per the bulletin; patched region present at android-security-16.0.0_r8 (7/8 lines).
- Android 17: not affected per the bulletin; patched region present at android-security-17.0.0_r1 (7/8 lines).
Unknowns
- The commit for the third item in the message (preventing unprivileged 3P snooze-with-context API calls, tested by NotificationManagerServiceTest) is not in the material; its content and branch coverage are unknown.
- The exact value of CONCURRENT_SNOOZE_LIMIT and the full set of SnoozeHelper paths that add or remove persisted entries are not shown.
- Why 1 of 8 lines of the patched region differs on the latest tags is not shown.
- How the patched region came to be present on Android 15, 16 and 17 is not shown.