CVE-2026-49913 AI-generated analysis
platform/hardware/interfaces, cas/aidl/default (default AIDL CAS HAL, IDescrambler implementation)
In the default AIDL CAS HAL, DescramblerImpl::descramble now compares the mmap() result for the client-supplied source SharedBuffer against MAP_FAILED instead of NULL, and installs a ScopeGuard that munmap()s the mapping on every exit path after the check.
Root cause
In cas/aidl/default/DescramblerImpl.cpp, DescramblerImpl::descramble tested the mmap() result for the source buffer with `if (srcPtr == NULL)`. mmap() returns MAP_FAILED, not NULL, on failure, so a failed mapping passed the check and execution continued with MAP_FAILED as the source pointer. The commit describes this as leading to an arbitrary-address memory access. The comment above the check notes that the offset and size in the SharedBuffer are client-controlled. The commit also adds munmap() cleanup 'to prevent memory leaks' of the mapping.
How the fix works
- cas/aidl/default/DescramblerImpl.cpp :: DescramblerImpl::descramble: the failure test changes from `srcPtr == NULL` to `srcPtr == MAP_FAILED`. On failure the function still logs 'Failed to map src buffer.' and returns toStatus(BAD_VALUE), so a failed mmap now stops the call before the pointer is used.
- cas/aidl/default/DescramblerImpl.cpp :: DescramblerImpl::descramble: right after the failure check, `::android::base::make_scope_guard` captures srcPtr and `size = srcBuffer.heapBase.size` and calls munmap(srcPtr, size) when the guard goes out of scope. This releases the mapping on every later return path, including the validateRangeForSize() check that follows.
- cas/aidl/default/DescramblerImpl.cpp: adds `#include <android-base/scopeguard.h>` for make_scope_guard.
Completeness
- Covers the source-buffer mmap() in DescramblerImpl::descramble: the failure check is now correct and the mapping is unmapped on all exit paths after the check.
- The ScopeGuard is installed after the MAP_FAILED check, so the failure path does not call munmap on a mapping that does not exist.
- The diff only touches the srcBuffer mapping. The material does not show the rest of descramble() (for example, whether a destination buffer is mapped with the same NULL-style check, or whether an existing munmap remains), so coverage of other mappings in this function or in the HIDL CAS HAL cannot be judged from the material.
- The guard unmaps srcBuffer.heapBase.size bytes. The mmap call is not shown, so the material does not confirm that the mapping used the same length.
Behavior changes
- A descramble() call whose source heap cannot be mapped now fails with BAD_VALUE (logged 'Failed to map src buffer.') instead of continuing with an invalid pointer.
- The source mapping is now released when descramble() returns, including on the validateRangeForSize() error path.
- Only the default HAL implementation changes; the diff does not touch the interface.
Per major
- Android 14: same fix: commit 8858a5521ba4 in android-security-14.0.0_r29, same hunk (file mode 100755, pre-image blob a96fd466bc, @@ -100,10 +101,14 @@). 7/8 lines of the patched region present at that tag.
- Android 15: same fix: commit 9bdc5c54c702 in android-security-15.0.0_r17, same hunk against blob 0f4e99b315. 7/8 lines of the patched region present.
- Android 16: same fix: commit 0b6f21543e54 in android-security-16.0.0_r8, same hunk against blob 0f4e99b315 (same pre-image as 15). 7/8 lines of the patched region present.
- Android 17: same fix: commit d9f6b94ba0f0 in android-security-17.0.0_r1, same hunk against blob f9c2a65e9f, shifted by one line (@@ -101,10 +102,14 @@). 7/8 lines of the patched region present.
Unknowns
- The rest of DescramblerImpl::descramble (the mmap call, any destination-buffer handling, any existing munmap) is not shown. Whether other mappings use the same incorrect check, or whether a fork's existing munmap would interact with the new ScopeGuard, is unknown.
- Whether the HIDL CAS HAL default implementation has the same pattern is not shown in the material.
- Which line of the 8-line patched region is missing at each security tag is not stated.
- The privilege boundary behind the High EoP rating is not shown beyond the bulletin rating.