CVE-2024-23710 AI-generated analysis
platform/frameworks/base, PackageManagerService install/scan (services/core/java/com/android/server/pm/InstallPackageHelper.java)
In InstallPackageHelper, two shared-user privilege checks (assertPackageWithSharedUserIdIsPrivileged and a second scan-time block guarded by SCAN_AS_PRIVILEGED and skipVendorPrivilegeScan) now also require !pkg.isLeavingSharedUser(), so packages leaving their shared user are excluded from both.
Root cause
Two conditions in InstallPackageHelper decided shared-user privilege handling from `!AndroidPackageUtils.isPrivileged(pkg) && pkg.getSharedUserId() != null` (the second also requires `(scanFlags & SCAN_AS_PRIVILEGED) == 0` and `!skipVendorPrivilegeScan`). They did not exclude packages for which pkg.isLeavingSharedUser() is true. The commit title says the fix stops marking apps as privileged when they are not signed properly. The diff shows the change itself is the added isLeavingSharedUser() exclusion.
How the fix works
- InstallPackageHelper.assertPackageWithSharedUserIdIsPrivileged: the guard becomes `!AndroidPackageUtils.isPrivileged(pkg) && pkg.getSharedUserId() != null && !pkg.isLeavingSharedUser()`. As a result, the SharedUserSetting lookup, the isPrivileged() test and the platform-signature comparison (which throws INTERNAL_ERROR_NOT_PRIV_SHARED_USER) are skipped for a package that is leaving its shared user.
- InstallPackageHelper, second hunk (around line 4783; the method name is not shown in the diff): `&& !pkg.isLeavingSharedUser()` is added to the guard `(scanFlags & SCAN_AS_PRIVILEGED) == 0 && !isPrivileged(pkg) && getSharedUserId() != null && !skipVendorPrivilegeScan`. The body of this block is not in the material.
- Single commit with two hunks; the same predicate is added to both.
Completeness
- Covers the two patched conditions in InstallPackageHelper.java.
- The fix only adds a predicate. It relies on pkg.isLeavingSharedUser() being computed correctly, which the material does not show.
- The material does not show whether other code paths derive privilege from getSharedUserId() without checking isLeavingSharedUser(). Per index search (which may be incomplete), no other caller of assertPackageWithSharedUserIdIsPrivileged was found.
Behavior changes
- A non-privileged package that declares a sharedUserId but is leaving it is no longer rejected with INTERNAL_ERROR_NOT_PRIV_SHARED_USER when that shared user is privileged and the package is not platform-signed.
- Such a package no longer enters the second guarded block (around line 4783). The effect of that block is not shown in the material.
- No API or error-code changes are visible; two install-time conditions are narrowed.
Per major
- Android 14: same fix: commit c7c1193ca755 in android-security-14.0.0_r7 (cherry-pick of 3ee5dfdcba04 / 06775341ad7d, Change-Id I5b5b81cf43b06837a22c8dfd170a112106dd64c1). At android-security-14.0.0_r29 the assertPackageWithSharedUserIdIsPrivileged hunk is present, and 7/8 lines of the patched region are present.
- Android 15: not affected per the bulletin; 6/8 lines of the patched region present at android-security-15.0.0_r17; exact code not shown.
- Android 16: not affected per the bulletin; 6/8 lines of the patched region present at android-security-16.0.0_r8; exact code not shown.
- Android 17: not affected per the bulletin; 6/8 lines of the patched region present at android-security-17.0.0_r1; exact code not shown.
Unknowns
- Name and body of the second patched method (the hunk around line 4783).
- The precise link between the commit title ('not signed properly') and the leaving-shared-user condition.
- How isLeavingSharedUser() is computed, and whether an installer-controlled manifest can set it.
- Android 13 code paths, and whether the Android 15+ trees contain the identical predicate (only line-match counts are given).