CVE-2026-28660 AI-generated analysis
platform/frameworks/base, package manager / PackageInstaller and LauncherApps system services
Adds a PackageInstallerService.getAllSessions(userId, filterCallingUid) overload and makes LauncherAppsService.getAllSessions pass the real caller UID into it. SessionInfo objects returned through LauncherApps.getAllPackageInstallerSessions() are therefore generated and filtered for the actual caller instead of for system_server.
Root cause
LauncherAppsService.LauncherAppsImpl.getAllSessions(String callingPackage) captures the caller's UID, then calls Binder.clearCallingIdentity() and invokes PackageInstallerService.getAllSessions(int userId) for each profile. Because identity was cleared, callingUid = Binder.getCallingUid() inside that method is system_server's UID. That UID went to session.generateInfoForCaller(false, callingUid) and to shouldFilterSession(snapshot, callingUid, info). The commit message says originatingUri and referrerUri were exposed, and the new javadoc describes the UID as 'used for SessionInfo scrubbing and filtering'. Together these indicate that generateInfoForCaller scrubs based on the UID and left the URIs intact for the system UID. Afterwards LauncherAppsService applied only its own shouldFilterSession(callingUid, info) (installer-UID match or canQueryPackage). That check removes whole sessions but does not scrub fields of the sessions it keeps. The result: an app calling LauncherApps.getAllPackageInstallerSessions() with package visibility to the session owner received unscrubbed originatingUri/referrerUri.
How the fix works
- services/core/java/com/android/server/pm/PackageInstallerService.java:getAllSessions(int userId): the Binder-facing method now reads Binder.getCallingUid() and delegates to a new package-private overload, getAllSessions(int userId, int filterCallingUid). Behavior for direct IPackageInstaller callers is unchanged.
- PackageInstallerService.java:getAllSessions(int, int): still calls snapshot.enforceCrossUserPermission(callingUid, ...) with Binder.getCallingUid(). When invoked from LauncherAppsService under cleared identity, that UID is system_server. It uses filterCallingUid for session.generateInfoForCaller(false, filterCallingUid) and for result.removeIf(info -> shouldFilterSession(snapshot, filterCallingUid, info)).
- services/core/java/com/android/server/pm/LauncherAppsService.java:LauncherAppsImpl.getAllSessions(String): inside the clearCallingIdentity block, the call changes from getAllSessions(userId) to getAllSessions(userId, callingUid). callingUid was captured before identity was cleared. The later LauncherAppsService.shouldFilterSession pass stays in place.
- Android 17 only: services/tests/mockingservicestests/.../PackageInstallerServiceTest.java adds testGetAllSessions_filtersSessionsCorrectly. The test exercises getAllSessions(int) filtering via canQueryPackage. It does not directly test the URI scrubbing or the two-argument overload.
Completeness
- Covers the identity-cleared internal path shown: LauncherAppsService.getAllSessions -> PackageInstallerService.getAllSessions. The index search (which may be incomplete) returned only LauncherAppsService as a caller, reached from LauncherApps.getAllPackageInstallerSessions(), and found no users outside frameworks/base.
- The direct Binder entry points getAllSessions(int), getSessionInfo(int) and getStagedSessions() are unchanged and keep using Binder.getCallingUid(), which is the right UID when they are called directly over Binder.
- The fix does not change what generateInfoForCaller scrubs. It only makes sure the right UID reaches it. The material does not show whether any other internal caller invokes these PackageInstallerService methods under clearCallingIdentity.
- The cross-user permission check in the new overload is still enforced against the Binder UID (system_server on the LauncherApps path), not filterCallingUid. LauncherAppsService already limits userIds to the caller's profiles beforehand, so this behavior is unchanged rather than a gap introduced by the fix.
- The Android 15 and 16 cherry-picks include no regression test. Only Android 17 carries one, and it covers filtering, not URI scrubbing.
Behavior changes
- LauncherApps.getAllPackageInstallerSessions() now returns SessionInfo objects generated for the calling app's UID, so originatingUri/referrerUri are scrubbed where they previously were not.
- On the LauncherApps path, PackageInstallerService.shouldFilterSession is now evaluated against the app caller's UID instead of the system UID, in addition to the existing LauncherAppsService.shouldFilterSession pass.
- No new exceptions, error codes or permission requirements appear in the diff. Direct IPackageInstaller.getAllSessions(int) callers see no change.
Per major
- Android 14: Not affected: the bulletin does not list Android 14, and the material contains no fix commit for it. The resolver reports 8/8 lines of the patched region present at android-security-14.0.0_r29.
- Android 15: Same fix: platform/frameworks/base 498791aa27ab in android-security-15.0.0_r17 (cherry-pick of bbeee4f37c25). Two files changed, no test added.
- Android 16: Same fix: platform/frameworks/base 3d614f9e98a3 in android-security-16.0.0_r8. The code change is identical, at shifted line offsets, with no test added.
- Android 17: Same fix plus a test: platform/frameworks/base 6acdd7f1a72d in android-security-17.0.0_r1. The code change is identical (the file already had a blank line before the return), plus a new PackageInstallerServiceTest.testGetAllSessions_filtersSessionsCorrectly.
Unknowns
- The body of PackageInstallerSession.generateInfoForCaller is not in the material. The claim that it scrubs originatingUri/referrerUri based on the caller UID rests only on the commit message and the new javadoc.
- The material does not show which UIDs or permissions generateInfoForCaller treats as privileged, that is, which callers still receive unscrubbed URIs.
- The body of PackageInstallerService.shouldFilterSession is not shown, so whether the set of listed sessions changes on the LauncherApps path is unknown.
- The material does not explain why Android 14 is not listed as affected even though the resolver finds the patched region lines present at android-security-14.0.0_r29.
- The material does not show whether other system-service callers invoke PackageInstallerService session-info methods under clearCallingIdentity. The index search found only LauncherAppsService.