CVE-2024-0024 AI-generated analysis
platform/frameworks/base, services/core com.android.server.pm.UserManagerService (multi-user / user restrictions persistence)
UserManagerService now truncates the user name and the seed account name and type to 500 characters at user creation, when seed account data is set, and when serializing the per-user XML, so an oversized string no longer causes the IOException that left user restrictions unwritten.
Root cause
The per-user XML serializer in UserManagerService wrote userData.seedAccountName, userData.seedAccountType and userInfo.name without any size limit. According to the commit message, extras too long to be serialized caused an IOException, and the restrictions were not written in the file. In the diff context the synchronized(mRestrictionsLock) block follows the TAG_NAME element in the same document. The result is a user created with no restrictions in place, observable after reboot per the commit test notes.
How the fix works
- UserManagerService.java: adds constant MAX_USER_STRING_LENGTH = 500 and helper truncateString(String). The helper returns the input unchanged if it is null or at most 500 chars, else original.substring(0, 500).
- UserManagerService.java (user XML serializer): the ATTR_SEED_ACCOUNT_NAME and ATTR_SEED_ACCOUNT_TYPE attributes and the TAG_NAME text are now written through truncateString().
- UserManagerService.java (user creation path): computes truncatedName = truncateString(name) up front. It uses it for convertPreCreatedUserIfPossible(userType, flags, truncatedName, token) and for new UserInfo(userId, truncatedName, null, flags, userType).
- UserManagerService.java (method that sets seed account data): stores truncateString(accountName) and truncateString(accountType) into userData. seedAccountOptions is stored unchanged.
- UserManagerServiceTest.java: the new test testCreateUserWithLongName_TruncatesName creates a user with a 66000-char name via createUserWithThrow and asserts the name length is 500. A 'Test' name stays 4 chars.
Completeness
- Covers the three string values touched in the serializer (user name, seed account name, seed account type), both at write time and where they are set (creation, seed account data).
- The approach bounds the inputs. It does not change the ordering of the XML write or make the restrictions block resilient to a serialization failure.
- userData.seedAccountOptions is stored without a size check in the diff. Whether it is serialized in the same document is not shown.
Behavior changes
- User names longer than 500 characters are silently truncated to 500 at creation. The returned UserInfo.name reflects the truncated value (the test asserts length 500).
- Seed account name and type longer than 500 characters are silently truncated when set and when persisted.
- No new error is reported to callers.
Per major
- Android 14: same fix: commit b8331285ad4f in android-security-14.0.0_r4 (Change-Id I633dc10974a64ef2abd07e67ff2d209847129989). At android-security-14.0.0_r29, 7/8 lines of the patched region are present. The shown r29 context of UserManagerService.java does not show MAX_USER_STRING_LENGTH between USER_VERSION and EPOCH_PLUS_30_YEARS.
- Android 15: not affected (not listed by the bulletin); at android-security-15.0.0_r17, 7/8 lines of the patched region are present.
- Android 16: not affected (not listed by the bulletin); at android-security-16.0.0_r8, 7/8 lines of the patched region are present.
- Android 17: not affected (not listed by the bulletin); at android-security-17.0.0_r1, 7/8 lines of the patched region are present.
Unknowns
- Which public API or intent path the triggering app used and what permission it required.
- The full list of fields serialized in the user XML (only the seed-data and name region is shown), so whether other oversized values could still abort the write is unknown.
- Which of the 8 patched lines is absent at the latest tags and why; the r29 context does not show MAX_USER_STRING_LENGTH at its original location.