CVE-2023-40110 AI-generated analysis
platform/frameworks/av, media/mtp (libmtp MtpPacket)
Adds bounds checks against mBufferSize to MtpPacket::getUInt16, getUInt32, putUInt16 and putUInt32 in media/mtp/MtpPacket.cpp, so reads abort and writes are dropped when offset plus field width exceeds the allocated buffer.
Root cause
MtpPacket::getUInt16/getUInt32/putUInt16/putUInt32 indexed mBuffer at offset, offset+1 (and up to offset+3) without comparing against mBufferSize. The commit message says the fuzzer found a write to a buffer index greater than the buffer size (heap OOB write). The read accessors had the same unchecked pattern.
How the fix works
- media/mtp/MtpPacket.cpp:MtpPacket::getUInt16: only performs the 2-byte read if (unsigned long)(offset+2) <= mBufferSize; otherwise it logs ALOGE and calls abort().
- media/mtp/MtpPacket.cpp:MtpPacket::getUInt32: only performs the 4-byte read if (unsigned long)(offset+4) <= mBufferSize; otherwise it logs ALOGE and calls abort().
- media/mtp/MtpPacket.cpp:MtpPacket::putUInt16: only performs the 2-byte write if (unsigned long)(offset+2) <= mBufferSize; otherwise it logs ALOGE and skips the write (no abort, no return value).
- media/mtp/MtpPacket.cpp:MtpPacket::putUInt32: only performs the 4-byte write if (unsigned long)(offset+4) <= mBufferSize; otherwise it logs ALOGE and skips the write.
- The cast is applied to the int sum offset+N, so the check rejects offsets whose sum exceeds mBufferSize or stays negative. Small negative offsets (for example -1) give a small non-negative sum and are not rejected by this check.
Completeness
- Covers the four fixed-width accessors in MtpPacket.cpp (two reads, two writes). They are checked against mBufferSize (allocation size), not mPacketSize (valid data length), so a read that is inside the allocation but past mPacketSize is still permitted.
- The checks do not reject small negative offsets whose sum with the field width is non-negative.
- Other direct mBuffer accesses in MtpPacket.cpp are untouched: copyFrom memcpys src.mPacketSize bytes after allocate(length), and dump() iterates to mPacketSize. This commit changes neither.
- Dropped writes fail silently (ALOGE only), so callers cannot tell that a putUInt16/putUInt32 was skipped. Out-of-range reads abort the process instead of returning an error.
- The MtpDataPacket::getUInt16(uint16_t&) overload shown by the index search reads mBuffer directly with its own checks and does not go through MtpPacket::getUInt16, so this change does not affect it.
Behavior changes
- Out-of-range getUInt16/getUInt32 now log an ALOGE and abort() the calling process instead of reading out of bounds.
- Out-of-range putUInt16/putUInt32 now log an ALOGE and do nothing instead of writing out of bounds.
- No API or return-type changes; in-range behavior is identical.
Per major
- Android 14: same fix: commit ce7ba619260d in android-security-14.0.0_r2 (cherry-picked from a669e34bb8e6, Change-Id Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b); 8/8 patched lines present at android-security-14.0.0_r29.
- Android 15: not affected (not listed by the bulletin); the patched lines are present at android-security-15.0.0_r17.
- Android 16: not affected (not listed by the bulletin); the patched lines are present at android-security-16.0.0_r8.
- Android 17: not affected (not listed by the bulletin); the patched lines are present at android-security-17.0.0_r1.
Unknowns
- The exact caller and offset computation behind the fuzzer-observed OOB write are not shown in the material.
- Whether the Android 11, 12, 12L and 13 branches received the same cherry-pick, and whether it applies cleanly there (only the Android 14 commit is provided).
- The material does not show which process hosts this code on Android 14, so the impact of the new abort() is not established here.
- Whether any caller can pass a small negative offset that passes the new check is not shown.