CVE-2024-31318 AI-generated analysis
platform/frameworks/base, services/companion (CompanionDeviceManagerService, CDM shell commands)
The CompanionDeviceManagerService binder implementation no longer overrides onShellCommand and instead overrides handleShellCommand. The base Binder.onShellCommand, which per the commit message checks the caller's permissions, therefore runs before CompanionDeviceShellCommand is executed.
Root cause
In services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java, the inner binder class overrode onShellCommand(FileDescriptor, FileDescriptor, FileDescriptor, String[], ShellCallback, ResultReceiver). The override unconditionally constructed a CompanionDeviceShellCommand (with the service's AssociationStore, DevicePresenceMonitor, TransportManager, SystemDataTransferRequestStore and AssociationRequestsProcessor) and called exec on it. Because this replaced Binder.onShellCommand, the caller permission check in Binder.onShellCommand was skipped. The commit message says: "Binder.onShellCommand checks the necessary permissions of the caller."
How the fix works
- CompanionDeviceManagerService.java (inner binder class): the onShellCommand override is removed and replaced by an override of int handleShellCommand(@NonNull ParcelFileDescriptor in, @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, @NonNull String[] args). The base Binder.onShellCommand is no longer overridden, so its caller permission check applies (per the commit message).
- The new handleShellCommand constructs the same CompanionDeviceShellCommand with the same arguments. It calls exec(this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), args) and returns the int result. The ShellCallback and ResultReceiver are no longer passed to exec.
- The imports of android.os.ResultReceiver and android.os.ShellCallback are removed because nothing uses them any more.
Completeness
- The fix covers the single shell-command entry point of the CompanionDeviceManagerService binder. CDM shell commands are now dispatched through the Binder.onShellCommand caller check.
- The fix adds no per-command permission checks inside CompanionDeviceShellCommand; it relies on the Binder-level check. No other files are touched.
- The material does not show whether other system services in this tree override onShellCommand in the same way.
Behavior changes
- Callers that fail the Binder.onShellCommand permission check can no longer reach CDM shell command execution.
- The shell command path now returns an int result through handleShellCommand instead of the void onShellCommand signature. The commit was tested manually on CDM shell commands.
Per major
- Android 14: same fix: commit 2442fb3428e7 in android-security-14.0.0_r9 (cherry-pick of 1761a0fee9c2). All 8 lines of the patched region are present at android-security-14.0.0_r29.
- Android 15: not affected per the bulletin; all 8 lines of the patched handleShellCommand region are present at android-security-15.0.0_r17.
- Android 16: not affected per the bulletin; all 8 lines of the patched region are present at android-security-16.0.0_r8.
- Android 17: not affected per the bulletin; all 8 lines of the patched region are present at android-security-17.0.0_r1.
Unknowns
- The material does not show the commits applied to Android 12, 12L and 13, which the bulletin lists as affected.
- Exactly which callers Binder.onShellCommand permits is not shown in the material.
- How ShellCallback and ResultReceiver are handled after the change is not shown.
- The exact name of the inner binder class is not visible in the diff hunk.
- The set of CDM shell commands exposed by CompanionDeviceShellCommand, and the impact of each, are not shown.
- Whether reaching the code depends on any device feature being present is not shown.