CVE-2025-48552 AI-generated analysis
platform/frameworks/base, DevicePolicyManagerService (services/devicepolicy), global HTTP proxy handling
Wraps the three Settings.Global proxy writes in DevicePolicyManagerService.saveGlobalProxyLocked in a try/catch, so an exception from SettingsProvider while applying a device admin's global proxy no longer aborts the caller (for example the removal of an ActiveAdmin).
Root cause
saveGlobalProxyLocked(String proxySpec, String exclusionList) parses an admin's global proxy spec and checks ProxyInfo.isValid(). It then calls mInjector.settingsGlobalPutString/PutInt for GLOBAL_HTTP_PROXY_HOST, GLOBAL_HTTP_PROXY_PORT and GLOBAL_HTTP_PROXY_EXCLUSION_LIST with no exception handling. If SettingsProvider threw while storing one of these values, the exception propagated out of saveGlobalProxyLocked into its caller. That caller iterates admins, applies the proxy of the first admin with specifiesGlobalProxy set, or otherwise resets the proxy to null. Per the commit message, this broke callers performing security-sensitive operations such as removing an ActiveAdmin.
How the fix works
- services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java:saveGlobalProxyLocked: the three mInjector.settingsGlobalPutString/settingsGlobalPutInt calls (host, port, exclusion list) are moved into a try block. Any Exception is caught, logged with Slogf.w(LOG_TAG, "Fail to save proxy", e) and otherwise ignored, so control returns normally to the caller.
- The same change also rewrites the Settings.Global.* constant references to Global.* in the 14 and 15 branches. This is cosmetic: the 16 branch already used Global.*.
- The ProxyInfo.isValid() early return before the writes was already there and is not changed. The fix only adds resilience against failures of the settings writes themselves.
Completeness
- Covers only the three Settings.Global writes inside saveGlobalProxyLocked. The parsing of proxySpec (split on ':', Integer.parseInt with NumberFormatException swallowed) and the ProxyInfo.isValid() check were already present and are not changed.
- The catch is catch (Exception), so any exception from the writes is swallowed, not a specific exception type.
- If the first or second put succeeds and a later one throws, the global proxy settings are left partially updated. The fix does not roll back or clear them.
- Other uses of mInjector.settingsGlobalPut* elsewhere in DevicePolicyManagerService are not touched by this commit. The material does not show whether similar failures there would matter.
Behavior changes
- A failure to persist the global proxy settings is now logged at warning level ("Fail to save proxy") and swallowed instead of propagating out of saveGlobalProxyLocked.
- Operations that re-apply or reset the global proxy (per the commit message, such as admin removal) now complete even when SettingsProvider rejects the stored proxy values.
- The proxy settings may be left partially written when a later put fails after an earlier one succeeded.
Per major
- Android 14: same fix: commit 58e0b9a15338 in android-security-14.0.0_r22 (cherry-pick of 2ea32931ef9a). The code context at android-security-14.0.0_r29 shows the try/catch present in saveGlobalProxyLocked (lines 8499-8507), even though the line-fingerprint resolver reports 1/4 lines.
- Android 15: same fix: commit bb6d2f17243d in android-security-15.0.0_r10, an identical diff (including the Settings.Global -> Global rename) at a different line offset.
- Android 16: same fix: commit d5fee58e64ae in android-security-16.0.0_r1. This branch already used Global.*, so only the try/catch is added. 4/4 patched lines are present at android-security-16.0.0_r8.
- Android 17: not affected (not listed by the bulletin). The resolver reports 1/4 patched lines at android-security-17.0.0_r1. The 17 source is not shown.
Unknowns
- Which exception SettingsProvider throws, and for which proxy host/port/exclusion-list values. The material only says invalid proxy settings cause errors (b/365975561).
- The name of the caller of saveGlobalProxyLocked and the full set of security-sensitive paths that reach it, beyond the commit message's example of removing an ActiveAdmin.
- Why the per-major resolver reports 1/4 patched lines for 14 and 15 while the 14 code context shows the full fix.
- Whether the Android 17 tree contains the try/catch (the source is not shown).