CVE-2025-48615 AI-generated analysis
platform/frameworks/base, system_server media session service (services/core/java/com/android/server/media/MediaButtonReceiverHolder.java)
Adds a 1024-character cap on media button receiver component names in MediaButtonReceiverHolder, first for components resolved from a PendingIntent (skipped with a warning) and then for ComponentName broadcast receivers (rejected with IllegalArgumentException).
Root cause
MediaButtonReceiverHolder accepted a media button receiver component name of any length. In getComponentName(PendingIntent, componentType) the ComponentName was built directly from componentInfo.packageName and componentInfo.name of the resolved PendingIntent target, and create(int userId, ComponentName broadcastReceiver) stored the caller-provided ComponentName as-is. The class also flattens the receiver to a string for persistence across boot (see unflattenFromString and its javadoc), so an overly long package or class name entered system_server state without any size check. The first commit message says the fix cannot be tested on main because PackageManager prevents it, so the input relied on a constraint that is not enforced at this layer. The material does not show the concrete consequence of an oversized name.
How the fix works
- Commit a1bbb371980e (MediaButtonReceiverHolder.java): introduces private static final int MAX_COMPONENT_NAME_LENGTH = 1024. In getComponentName(PendingIntent, componentType), inside the loop over resolved components and after the existing creator-package and null checks, it computes componentInfo.packageName.length() + componentInfo.name.length() + 1. If the result is greater than 1024, it logs 'detected and ignored component name with overly long package or name' and continues to the next candidate instead of returning a ComponentName.
- Commit e20813dba23a (MediaButtonReceiverHolder.java): adds private static boolean componentNameTooLong(ComponentName), which applies the same packageName + className + 1 > MAX_COMPONENT_NAME_LENGTH test. create(int userId, ComponentName broadcastReceiver) now calls it first and throws IllegalArgumentException("receiver name too long") before constructing the holder. getComponentName(PendingIntent, ...) is refactored to build the ComponentName first and call componentNameTooLong on it; the skip-and-log behavior is unchanged. Per the commit message, this closes the setMediaButtonBroadcastReceiver(ComponentName) path that the first change missed.
Completeness
- After both commits, both create overloads that take an app-supplied receiver are checked: the PendingIntent path via getComponentName(PendingIntent, componentType) and the ComponentName path via create(int, ComponentName).
- The first commit alone covers only the PendingIntent path. The ComponentName broadcast receiver path is covered only by the second commit.
- unflattenFromString(Context, String), which restores the receiver from persisted storage, is not modified. It still calls ComponentName.unflattenFromString(tokens[0]) without a length check, so previously persisted values are not re-validated by this diff.
- The fallback constructor MediaButtonReceiverHolder(userId, pendingIntent, sessionPackageName), used when the PendingIntent component cannot be resolved, is unchanged. It stores sessionPackageName without a length check (the javadoc says the session package name is assumed to be already validated).
- The check counts Java String length (chars), not bytes.
Behavior changes
- PendingIntent media button receivers whose resolved package name + class name + 1 exceeds 1024 characters are skipped with a Log.w. If no other candidate matches, create(int, PendingIntent, String) falls back to the component-less holder (COMPONENT_TYPE_INVALID) with only the session package name, as it already did for unresolvable intents.
- create(int userId, ComponentName broadcastReceiver) now throws IllegalArgumentException("receiver name too long") for component names over 1024 characters, where it previously always succeeded.
- New constant MAX_COMPONENT_NAME_LENGTH = 1024 and new private helper componentNameTooLong(ComponentName).
Per major
- Android 14: same fix, both commits: a1bbb371980e in android-security-14.0.0_r24 (PendingIntent path) and e20813dba23a in android-security-14.0.0_r25 (ComponentName path plus helper). At android-security-14.0.0_r29, 8/8 lines of the patched region are present.
- Android 15: same fix for the first commit: 8f8c16cee29b in android-security-15.0.0_r12, identical diff to Android 14. At android-security-15.0.0_r17, 8/8 lines are present. The material does not show whether the second commit (ComponentName path) was applied on 15.
- Android 16: same fix for the first commit: a5795fc0cf1f in android-security-16.0.0_r3, identical diff to Android 14. At android-security-16.0.0_r8, 8/8 lines are present. The material does not show whether the second commit (ComponentName path) was applied on 16.
- Android 17: resolved in base: the second commit 013bb57034ee is in android-17.0.0_r1, and its parent blob (ffa2bcbd6fd2) is the file after the first commit, so both changes are present. At android-security-17.0.0_r1, 6/8 lines of the patched region are present. The second commit rewrites three of the first commit's added lines; the material does not explain the exact 6/8 count.
Unknowns
- The material does not show the concrete effect of an overly long component name, that is, what fails in system_server or in the persisted-state path and how that leads to the bulletin's EoP rating.
- Whether the second commit (ComponentName broadcast receiver path) was merged to the Android 15 and 16 security branches. Only the first commit is shown for those majors.
- How the IllegalArgumentException from create(int, ComponentName) propagates to the calling app. The MediaSessionRecord/MediaSessionService call sites are not in the material.
- Why the patched-region check reports 6/8 lines on Android 17 but 8/8 on Android 14 r29, although both contain the second commit.
- Why 1024 was chosen as the limit and whether it matches PackageManager's own component name constraint.