CVE-2025-26436 AI-generated analysis
platform/frameworks/base, ActivityManager PendingIntentRecord (background start / temp allowlist privileges of PendingIntents)
PendingIntentRecord.clearAllowBgActivityStarts now also downgrades the token's duration-based temp-allowlist entry from TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED to TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED, instead of only removing the token from the BAL token sets; a companion commit adds equals/hashCode to BackgroundStartPrivileges for the tests.
Root cause
PendingIntentRecord keeps two kinds of background-start privilege state per allowlist token: the token sets mAllowBgActivityStartsForActivitySender / mAllowBgActivityStartsForBroadcastSender / mAllowBgActivityStartsForServiceSender, and the duration-based map mAllowlistDuration (TempAllowListDuration with a duration and a type). clearAllowBgActivityStarts(IBinder token) only removed the token from the three sets and left the mAllowlistDuration entry untouched (commit message: 'only cleared the tokens, but kept the duration based entries'), so an entry with type TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED stayed in place after the caller (per the commit message, SystemUI in NotificationManagerService) cleared the BAL privileges of that PendingIntent.
How the fix works
- Commit 88d7046ea668 (test support only): core/java/android/app/BackgroundStartPrivileges.java makes the class final and adds equals() and hashCode() over mAllowsBackgroundActivityStarts, mAllowsBackgroundForegroundServiceStarts and mOriginatingToken; adds backgroundStartPrivilege_equals_works to BackgroundStartPrivilegesTest. No runtime behavior change beyond value equality.
- Commit c8ac5c6dec12 (the actual fix): services/core/java/com/android/server/am/PendingIntentRecord.java:clearAllowBgActivityStarts, after removing the token from the three sender sets, checks mAllowlistDuration != null, looks up mAllowlistDuration.get(token), and if the entry is non-null with type TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED sets its type to TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED. The entry and its duration are kept.
- Same commit adds @VisibleForTesting getAllowlistDurationLocked(IBinder) and makes getBackgroundStartPrivilegesForActivitySender @VisibleForTesting (was private); adds testClearAllowBgActivityStartsClearsToken and testClearAllowBgActivityStartsClearsDuration to PendingIntentControllerTest, the latter asserting the entry stays non-null with duration 1000 while type becomes FOREGROUND_SERVICE_NOT_ALLOWED.
Completeness
- Covers only the token passed to clearAllowBgActivityStarts; the three token sets and the mAllowlistDuration entry for that token are handled.
- The mAllowlistDuration entry is not removed; only type FOREGROUND_SERVICE_ALLOWED is rewritten to FOREGROUND_SERVICE_NOT_ALLOWED, so the duration entry itself remains for that token.
- Entries with any other type are left unchanged (the condition only matches FOREGROUND_SERVICE_ALLOWED).
- No change to setAllowlistDurationLocked, setAllowBgActivityStarts or the send path; the fix is confined to the clear path. The commit message states clearAllowBgActivityStarts is used exclusively by SystemUI (in NotificationManagerService).
- Not flag guarded (Flag: EXEMPT bugfix).
Behavior changes
- After clearAllowBgActivityStarts(token), the mAllowlistDuration entry for that token has type FOREGROUND_SERVICE_NOT_ALLOWED instead of FOREGROUND_SERVICE_ALLOWED; the entry and its duration remain.
- BackgroundStartPrivileges is now final and has value-based equals/hashCode (commit says used only in tests for now).
Per major
- Android 14: same fix: both commits (88d7046ea668 equals/hashCode, c8ac5c6dec12 clearAllowBgActivityStarts duration downgrade, the latter RESTRICT AUTOMERGE) are in android-security-14.0.0_r20; at android-security-14.0.0_r29 7/8 lines of the patched region are present.
- Android 15: same fix: resolved in android-security-15.0.0_r8; the material shows the equals/hashCode commit (bba26504af51) as an identical diff at different line offsets. The PendingIntentRecord commit for 15 is not shown; 7/8 lines of the patched region are 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
- The material does not show the PendingIntentRecord commit as applied on Android 15 (only the equals/hashCode commit is shown), nor which 7 of 8 lines of the patched region are present in each latest tag.
- How the mAllowlistDuration entry is consumed on PendingIntent send, and the concrete EoP impact, are not shown beyond the bulletin rating and commit message.
- Whether Android 13 (listed as affected) received an equivalent change is not shown.