CVE-2024-23705 AI-generated analysis
platform/frameworks/base, UserManagerService / UserManager / ConfirmUserCreationActivity (multi-user, seed account data)
Adds string-length limits for user name, seed account name/type and seed accountOptions so that an oversized PersistableBundle is dropped in UserManagerService.setSeedAccountData and rejected in ConfirmUserCreationActivity instead of being persisted, where per the PersistableBundle comment an over-long string makes the XML write throw.
Root cause
UserManagerService.setSeedAccountData stored the caller-supplied accountOptions PersistableBundle into userData.seedAccountOptions with no check on the length of its String keys/values (only seedAccountName/seedAccountType and the user name were truncated to a 500-char MAX_USER_STRING_LENGTH). The new PersistableBundle comment states that strings longer than 65535 characters cannot be saved to XML as part of a bundle and an IOException is thrown, so persisting the user record with an oversized bundle fails. Per the commit message, this resulted in a user being created with no restrictions. ConfirmUserCreationActivity also passed user name, account name, account type and accountOptions through without any length check.
How the fix works
- core/java/android/os/PersistableBundle.java: new @hide isBundleContentsWithinLengthLimit(int limit) walks mMap after unparcel(); returns false if any key, String value, element of a String[] value, or (recursively) any nested PersistableBundle exceeds limit.
- core/java/android/os/UserManager.java: adds @hide constants MAX_USER_NAME_LENGTH = 100, MAX_ACCOUNT_STRING_LENGTH = 500, MAX_ACCOUNT_OPTIONS_LENGTH = 1000 and documents the limits in the createUserCreationIntent javadoc.
- services/core/java/com/android/server/pm/UserManagerService.java: removes MAX_USER_STRING_LENGTH; truncateString now takes a limit. setSeedAccountData truncates accountName/accountType to MAX_ACCOUNT_STRING_LENGTH and only assigns userData.seedAccountOptions when accountOptions != null && isBundleContentsWithinLengthLimit(MAX_ACCOUNT_OPTIONS_LENGTH); otherwise the assignment is skipped (seedAccountOptions is null in the test after clearSeedAccountData). The user XML serialization code truncates seed account name/type to 500 and user name to 100; the internal create-user method truncates name to MAX_USER_NAME_LENGTH (100).
- core/java/com/android/internal/app/ConfirmUserCreationActivity.java: checkUserCreationRequirements adds a branch after the cantCreateUser check: if mUserName > 100, mAccountName or mAccountType > 500, or mAccountOptions fails isBundleContentsWithinLengthLimit(1000), it sets result USER_CREATION_FAILED_NOT_PERMITTED, logs, and returns null (same handling as the cantCreateUser branch).
- Tests: UserManagerServiceTest adjusted to MAX_USER_NAME_LENGTH; UserManagerTest adds testAddUserAccountData_validStringValuesAreSaved_validBundleIsSaved and testAddUserAccountData_invalidStringValuesAreTruncated_invalidBundleIsDropped.
Completeness
- Covers the service entry point (setSeedAccountData) and the UI entry point (ConfirmUserCreationActivity); other paths, if any, are not visible in the material.
- isBundleContentsWithinLengthLimit bounds individual String key/value lengths (including String[] elements and nested bundles) but not the number of entries or the total serialized size of the bundle; non-String value types are not inspected.
- In the service the bundle is silently dropped (no log) rather than rejected with an error to the caller; name/type are truncated rather than rejected. The activity path rejects outright.
- Only the setSeedAccountData assignment of seedAccountOptions is guarded; the diff does not show any other writer of userData.seedAccountOptions, so whether others exist is not visible in the material.
Behavior changes
- User name truncation limit lowered from 500 to 100 characters (internal create-user path and user XML serialization); existing test updated accordingly.
- setSeedAccountData: accountOptions containing any String key/value longer than 1000 chars is not stored (getSeedAccountOptions returns null in the test); accountName/accountType truncated to 500.
- ConfirmUserCreationActivity now sets USER_CREATION_FAILED_NOT_PERMITTED when any supplied property exceeds its limit, checked before the no-more-users check.
Per major
- Android 14: same fix: commit 147715e733e6 in android-security-14.0.0_r7 (cherry-pick of 33a90988cf3b); patched region fully present at android-security-14.0.0_r29 (8/8 lines).
- Android 15: not affected per the bulletin; the patched code is present at android-security-15.0.0_r17 (8/8 lines), i.e. the branch carries the fix.
- Android 16: not affected per the bulletin; patched code present at android-security-16.0.0_r8 (8/8 lines).
- Android 17: not affected per the bulletin; patched code present at android-security-17.0.0_r1 (8/8 lines).
Unknowns
- The exact failure mode by which an oversized bundle leaves the user without restrictions (the user XML write path and how a serializer exception is handled) is only indicated by the commit title and the PersistableBundle comment, not shown in the diff.
- Permission/caller requirements of setSeedAccountData and whether ConfirmUserCreationActivity is exported to untrusted apps are not shown.
- How the caller of checkUserCreationRequirements handles a null return is not shown.
- The corresponding commits for Android 12, 12L and 13 are not in the material.