CVE-2025-48585 AI-generated analysis
platform/packages/modules/Profiling, ProfilingService (system-triggered profiling triggers, IProfilingService binder)
ProfilingService now verifies, via PackageManager.getPackagesForUid, that the package name supplied by the client to addProfilingTriggers, removeProfilingTriggers and clearProfilingTriggers actually belongs to Binder.getCallingUid(), throwing SecurityException otherwise.
Root cause
In service/java/com/android/os/profiling/ProfilingService.java, addProfilingTriggers(List<ProfilingTriggerValueParcel>, String packageName), removeProfilingTriggers(int[], String packageName) and clearProfilingTriggers(String packageName) take the package name as a plain binder argument. The manager side (ProfilingManager in framework/java/android/os/ProfilingManager.java, per index search) passes mContext.getPackageName(). The service never checked that this string belonged to the calling UID. removeProfilingTriggers and clearProfilingTriggers use it directly, together with Binder.getCallingUid(), as a key into mAppTriggers, and addProfilingTriggers processes triggers for it. A binder client could therefore supply an arbitrary, empty or null package name and have trigger state handled under that name. The bulletin classifies the result as a High severity DoS. The material does not show the exact DoS mechanism.
How the fix works
- service/java/com/android/os/profiling/ProfilingService.java: adds a new private helper, enforceCallerMatchesPackageName(String packageName). It throws SecurityException in three cases: (1) the name is null or empty; (2) mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid()) returns null or an empty array; (3) packageName does not equal any of the returned package names.
- ProfilingService.addProfilingTriggers: calls enforceCallerMatchesPackageName(packageName) as its first statement, before reading Binder.getCallingUid() and iterating over the supplied triggers.
- ProfilingService.removeProfilingTriggers: calls enforceCallerMatchesPackageName(packageName) before mAppTriggers.get(packageName, Binder.getCallingUid()).
- ProfilingService.clearProfilingTriggers: calls enforceCallerMatchesPackageName(packageName) before mAppTriggers.remove(packageName, Binder.getCallingUid()).
- Single commit (1215317dfc1d) adding 39 lines, with no other files touched.
Completeness
- Covers the three trigger-management entry points that take a caller-supplied package name: addProfilingTriggers, removeProfilingTriggers and clearProfilingTriggers.
- The check accepts any package returned by getPackagesForUid for the calling UID, so validation works at UID granularity. This is consistent with mAppTriggers being keyed by both package name and calling UID.
- The commit message calls for an audit of IProfilingService for other cases of callers supplying incorrect information. The diff changes only these three methods, and the material does not show whether other IProfilingService methods take caller-supplied identity data.
- The fix does not touch server-side trigger delivery (ActivityManagerService.sendProfilingTrigger -> ProfilingServiceHelper.onProfilingTriggerOccurred(uid, packageName, triggerType), per index search). That path starts in ActivityManagerService, not in an app caller of IProfilingService.
Behavior changes
- addProfilingTriggers, removeProfilingTriggers and clearProfilingTriggers now throw SecurityException when the package name is null, empty, or not associated with the calling UID.
- Calls from a UID for which PackageManager returns no packages are now rejected with SecurityException, even if the package name is otherwise well-formed.
- Legitimate callers going through ProfilingManager, which passes mContext.getPackageName(), should be unaffected as long as that package name belongs to the calling UID.
Per major
- Android 14: not affected per the bulletin (not listed). packages/modules/Profiling is not present in android-security-14.0.0_r29.
- Android 15: not affected per the bulletin (not listed). At android-security-15.0.0_r17, 5/8 lines of the patched region are present. The material does not show which of the trigger methods exist there or whether any change was applied.
- Android 16: same fix: commit 1215317dfc1d in android-security-16.0.0_r4, a cherry-pick of internal changes (Cherrypick-From aef103928d0380e0a4bb24e13768a844e9698413, Change-Id I8a9a663776c7d4ea8bbb6ca789d805256625674c). 8/8 lines of the patched region are present at android-security-16.0.0_r8.
- Android 17: not affected per the bulletin (not listed). At android-security-17.0.0_r1, 6/8 lines of the patched region are present. The material does not show how, or whether, the fix landed there.
Unknowns
- The concrete DoS consequence of a spoofed, null or empty package name (what breaks downstream in trigger storage or delivery) is not shown in the material.
- How addProfilingTriggers stores triggers (the loop body) is not shown in the diff.
- Whether other IProfilingService methods accept caller-supplied identity data, and whether the audit mentioned in the commit message led to further changes.
- How the fix reached Android 17 (6/8 lines present), and what the partial region on Android 15 (5/8 lines) contains.