CVE-2025-48554 AI-generated analysis
platform/frameworks/base, DevicePolicyManagerService / DeviceAdminInfo (device admin metadata handling)
DevicePolicyManagerService now re-parses an active admin's device-admin metadata whenever its package changes and drops the admin if the metadata is malformed, and DeviceAdminInfo converts an OutOfMemoryError raised while parsing that metadata into an XmlPullParserException so callers can handle it.
Root cause
In DevicePolicyManagerService.handlePackagesChanged, when an active admin's package changed, the service only used mIPackageManager.getPackageInfo and getReceiverInfo to check that the package and the receiver component still existed. It never re-validated the admin's device-admin meta-data, so an updated DPC APK could remain an active admin while carrying malformed metadata. Separately, the metadata parsing block of the DeviceAdminInfo(Context, ActivityInfo) constructor caught only NameNotFoundException. An OutOfMemoryError thrown while parsing the meta-data XML therefore propagated as an Error instead of an XmlPullParserException.
How the fix works
- core/java/android/app/admin/DeviceAdminInfo.java: DeviceAdminInfo(Context, ActivityInfo) adds 'catch (OutOfMemoryError e)' next to the existing NameNotFoundException catch and rethrows it as XmlPullParserException("Out of memory when parsing", null, e). Callers that catch Exception or XmlPullParserException can now handle the failure.
- services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java: adds a new helper, isActiveAdminPackageValid(ActiveAdmin admin), annotated @GuardedBy(getLockObject()). It (1) returns false if mIPackageManager.getPackageInfo(adminPackage, 0, userHandle) is null, (2) fetches the receiver with GET_META_DATA | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE (GET_META_DATA is new compared with the old inline check) and returns false if the result is null, (3) constructs new DeviceAdminInfo(mContext, ai) inside try/catch(Exception) and, if parsing throws, logs 'contains malformed metadata' and returns false. userHandle is taken from admin.getUserHandle().getIdentifier().
- services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java: handlePackagesChanged replaces the inline getPackageInfo/getReceiverInfo null checks with '!isActiveAdminPackageValid(aa)'. On failure the existing removal path runs unchanged: remove the admin from policy.mAdminList and policy.mAdminMap, then call pushActiveAdminPackagesLocked and pushMeteredDisabledPackages. The log message now reads 'not found or invalid' and passes format arguments to Slogf.e directly instead of using String.format.
- The two parts depend on each other. isActiveAdminPackageValid catches Exception, which does not catch OutOfMemoryError. The DeviceAdminInfo change is what makes an OOM during parsing surface as a catchable XmlPullParserException.
Completeness
- Covers the package-change path (handlePackagesChanged) for every active admin in policy.mAdminList of the affected user, both for a specific packageName and for the packageName == null (check all) case.
- The OutOfMemoryError conversion is limited to the metadata parsing try block of DeviceAdminInfo(Context, ActivityInfo). It does not cover other Error subclasses, and the catch (Exception e) in isActiveAdminPackageValid would not catch any Error that is not converted there.
- This commit does not change other places that construct DeviceAdminInfo. The material does not show whether those places already tolerate XmlPullParserException.
- Validation is triggered only through handlePackagesChanged. Admins are not re-validated by this change outside that path.
Behavior changes
- An active admin whose updated package has device-admin meta-data that fails DeviceAdminInfo parsing is now removed as an active admin. The side effects are the same as for an uninstalled admin: it is removed from mAdminList and mAdminMap, and the active admin packages and metered-disabled packages are pushed.
- getReceiverInfo in this path now requests GET_META_DATA.
- DeviceAdminInfo(Context, ActivityInfo) now throws XmlPullParserException, with the OutOfMemoryError as its cause, instead of letting OutOfMemoryError propagate from the metadata parsing block.
- New error log lines: '<pkg> no longer installed', '<pkg> no longer has the receiver', '<pkg> contains malformed metadata', and the reworded 'Admin package %s not found or invalid for user %d, removing active admin'.
Per major
- Android 14: same fix: platform/frameworks/base 0f9ca51bfd42 in android-security-14.0.0_r22 (cherry-picked, Change-Id I1743c111f8e8b5f4c1f878a61b88b8f1ed6b86a1); 8/8 patched lines present at android-security-14.0.0_r29.
- Android 15: same fix: platform/frameworks/base 660c7075dc00 in android-security-15.0.0_r10, same content at different line offsets; 8/8 lines present at android-security-15.0.0_r17.
- Android 16: same fix: platform/frameworks/base c0978bc04a25 in android-security-16.0.0_r1; the only difference is that the pre-fix inline check already used bare MATCH_DIRECT_BOOT_* names; 8/8 lines present at android-security-16.0.0_r8.
- Android 17: not affected (not listed by the bulletin); the patched region is present 8/8 at android-security-17.0.0_r1.
Unknowns
- Where the malformed or oversized metadata was parsed and caused the DoS before the fix, which process was affected, and whether the effect persisted across reboots.
- Whether other DeviceAdminInfo construction sites in DevicePolicyManagerService already handle XmlPullParserException; the material does not show them.
- The specific nature of the malformed metadata that triggered the OutOfMemoryError (the commit says 'Test: manual' and includes no test case).