CVE-2024-49745 AI-generated analysis
platform/frameworks/native, libbinder (libs/binder/Parcel.cpp, Parcel growth/write path)
Parcel::growData in libbinder now rejects a grow request with BAD_VALUE when the current data position is beyond the data size, instead of going ahead with growth that per the commit message used to abort or could request a very large allocation.
Root cause
Parcel::growData(len) is only expected to be called at the end of a Parcel, as the new log message says. Before the fix it checked len and overflow (len > SIZE_MAX - mDataSize, mDataSize + len > SIZE_MAX / 3) and computed newSize = ((mDataSize+len)*3)/2 without looking at mDataPos. Parcel::setDataPosition(pos) only rejects pos > INT32_MAX and does not clamp pos to mDataSize, so a Parcel can end up with mDataPos > mDataSize. Per the commit message, that case "used to abort", and allocating that much memory "may cause OOM or other issues".
How the fix works
- libs/binder/Parcel.cpp:Parcel::growData: after an existing check that returns BAD_VALUE, and before the overflow checks and the newSize computation, the fix adds `if (mDataPos > mDataSize)`. That branch logs via ALOGE ("growData only expected at the end of a Parcel", printing pos, len and capacity) and returns BAD_VALUE.
- The added comment says mDataPos < mDataSize is also unexpected but is deliberately tolerated because it only wastes some memory. Only the mDataPos > mDataSize case is rejected.
- Single-commit fix in one file. setDataPosition, continueWrite and the callers are not changed.
Completeness
- Covers only Parcel::growData in libs/binder/Parcel.cpp. Any write path that reaches growData with mDataPos > mDataSize now fails with BAD_VALUE instead of growing the buffer.
- Parcel::setDataPosition is unchanged and still accepts any pos <= INT32_MAX regardless of mDataSize, so the inconsistent state can still be created. Only the growth step rejects it.
- The mDataPos < mDataSize case is explicitly left unhandled (tolerated as wasted memory).
- Per index search, the separate copy of growData in system/libhwbinder/Parcel.cpp has no mDataPos check, and this commit does not touch it.
Behavior changes
- Parcel::growData returns BAD_VALUE (a new error path) when mDataPos > mDataSize. Before, the call went ahead and, per the commit message, could abort.
- A new ALOGE log line is emitted in that case.
- Writes that need to grow the buffer while the data position is beyond the data size now return an error status instead of growing the buffer.
Per major
- Android 14: same fix: commit 01a1e3492999 in android-security-14.0.0_r16 (cherry-pick of 608524d46227). All 4 added lines are present at android-security-14.0.0_r29.
- Android 15: same fix: commit df99a3903097 in android-security-15.0.0_r4, an identical hunk at a different line offset (@@ -2942). 4/4 lines are present at android-security-15.0.0_r17.
- Android 16: not affected (not listed by the bulletin). The patched region is present (4/4 lines) at android-security-16.0.0_r8.
- Android 17: not affected (not listed by the bulletin). Only 2/4 lines of the patched region match at android-security-17.0.0_r1, and the material does not show the current form of the code.
Unknowns
- The concrete trigger path, and which process or privilege boundary gives the EoP rating, are not shown in the material.
- Where exactly the pre-fix abort happened, or whether a given case led to an oversized allocation, is not shown. The commit message only mentions both outcomes.
- What the Android 17 code looks like, given that only 2/4 lines of the patched region match.
- Whether the libhwbinder Parcel can reach a state with mDataPos > mDataSize.