CVE-2025-48553 AI-generated analysis
platform/frameworks/base, DevicePolicyManagerService / DeviceAdminInfo (device policy)
DevicePolicyManagerService.handlePackagesChanged now re-parses the device admin metadata of an active admin's receiver (via a new DeviceAdminInfo) after a package change and removes the admin if the package, receiver or metadata is missing or malformed; DeviceAdminInfo's metadata parser additionally converts OutOfMemoryError into XmlPullParserException so that failure is catchable.
Root cause
In handlePackagesChanged, when an active admin's package changed, DPMS only verified via mIPackageManager.getPackageInfo and getReceiverInfo (without GET_META_DATA) that the package and the receiver component still existed. It never re-read or re-parsed the receiver's device admin metadata, so an ActiveAdmin stayed registered with its previously stored DeviceAdminInfo even if the updated package's receiver no longer carried well-formed device admin metadata. Additionally, DeviceAdminInfo(Context, ActivityInfo) only caught NameNotFoundException around the XML parse; an OutOfMemoryError during parsing propagated as an Error rather than a parse failure.
How the fix works
- core/java/android/app/admin/DeviceAdminInfo.java: constructor DeviceAdminInfo(Context, ActivityInfo) adds `catch (OutOfMemoryError e)` that rethrows as XmlPullParserException("Out of memory when parsing", null, e). This turns an OOM during metadata parsing into a checked parse exception that callers catching Exception can handle.
- services/devicepolicy/.../DevicePolicyManagerService.java: new @GuardedBy(getLockObject()) helper isActiveAdminPackageValid(ActiveAdmin admin). It (1) returns false if mIPackageManager.getPackageInfo(adminPackage, 0, userHandle) is null, (2) fetches the receiver with getReceiverInfo(component, GET_META_DATA | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userHandle) and returns false if null, (3) constructs `new DeviceAdminInfo(mContext, ai)` and returns false if any Exception is thrown (logged as 'contains malformed metadata'). The userHandle comes from admin.getUserHandle().getIdentifier().
- DevicePolicyManagerService.handlePackagesChanged: replaces the inline existence check with `if (!isActiveAdminPackageValid(aa))`; on failure it removes the admin from policy.mAdminList and policy.mAdminMap, calls pushActiveAdminPackagesLocked and pushMeteredDisabledPackages, and sets removedAdmin/removedAdminPackage as before. The log message is changed to 'not found or invalid'.
- The two file changes are coupled: isActiveAdminPackageValid catches Exception only, so without the DeviceAdminInfo change an OutOfMemoryError in parsing would still escape the check.
Completeness
- Covers the package-change path only: validation is performed in handlePackagesChanged for admins whose package matches (or all admins when packageName is null).
- The newly parsed DeviceAdminInfo is discarded; the stored aa.info is not refreshed in this path, so if the metadata parses but differs (e.g. different uses-policies), the admin keeps its previously stored info as far as this code shows.
- Only Exception is caught around the DeviceAdminInfo constructor; Errors other than the now-converted OutOfMemoryError are not handled.
- Other places that construct DeviceAdminInfo or load admins (e.g. at boot/settings load) are not shown in the material; whether they already re-validate metadata is unknown.
Behavior changes
- Active admins whose updated package has a receiver but missing/malformed device admin metadata are now removed on package change (previously retained).
- getReceiverInfo in this path now requests GET_META_DATA.
- DeviceAdminInfo(Context, ActivityInfo) now throws XmlPullParserException instead of propagating OutOfMemoryError during metadata parsing; this affects every caller of that constructor, not only DPMS.
- New error log lines: '<pkg> no longer installed', '<pkg> no longer has the receiver', '<pkg> contains malformed metadata', and '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; both files changed; 8/8 patched lines present at android-security-14.0.0_r29.
- Android 15: same fix: 660c7075dc00 in android-security-15.0.0_r10; same diff content at different line offsets; 8/8 lines present at android-security-15.0.0_r17.
- Android 16: same fix: c0978bc04a25 in android-security-16.0.0_r1; same except the removed code already used unqualified MATCH_DIRECT_BOOT_* constants; 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
- The exact privilege gained (what the retained admin could do with stale DeviceAdminInfo after a malformed update) is not shown; the bulletin only rates it High EoP.
- Whether other admin-loading paths (boot-time settings load, setActiveAdmin) already validate metadata is not shown in the material.
- The commit lists two bugs (384514657, 414603411); which one maps to this CVE is not shown.
- The visibility of the DeviceAdminInfo(Context, ActivityInfo) constructor and its full set of callers are not shown.