CVE-2024-0030 AI-generated analysis
platform/packages/modules/Bluetooth, system/btif GATT server (btif_gatt_util.cc)
Clamps the GATT server response length to GATT_MAX_ATTR_LEN and copies only that many bytes in btif_to_bta_response, instead of always copying GATT_MAX_ATTR_LEN bytes and passing through an unchecked length.
Root cause
In system/btif/src/btif_gatt_util.cc, btif_to_bta_response() converted a btgatt_response_t (p_src) into a tGATTS_RSP (p_dest). It copied p_src->attr_value.len into p_dest->attr_value.len unchanged, without checking it against GATT_MAX_ATTR_LEN. It then called memcpy(p_dest->attr_value.value, p_src->attr_value.value, GATT_MAX_ATTR_LEN) whatever the actual length was. Per the commit message, the valid size of p_src->attr_value.value depends on p_src->attr_value.len, so the fixed-size copy can read past the valid source data. Also per the commit message, p_dest->attr_value.len did not match the length of p_dest->attr_value.value, so downstream code (attp_build_value_cmd) could read out of bounds.
How the fix works
- system/btif/src/btif_gatt_util.cc:btif_to_bta_response: p_dest->attr_value.len is now set to std::min<uint16_t>(p_src->attr_value.len, GATT_MAX_ATTR_LEN), so the destination length is capped at GATT_MAX_ATTR_LEN. This addresses the second issue in the commit message (OOB read in attp_build_value_cmd through an oversized len).
- system/btif/src/btif_gatt_util.cc:btif_to_bta_response: the memcpy now copies p_dest->attr_value.len bytes (the clamped length) instead of a constant GATT_MAX_ATTR_LEN, so only the first len bytes of p_src->attr_value.value are read. This addresses the first issue in the commit message (OOB read of the source).
- system/btif/src/btif_gatt_util.cc: adds #include <algorithm> for std::min.
Completeness
- Within btif_to_bta_response, the fix covers both the source over-read (fixed-size memcpy) and the destination length mismatch. Per index search, the only caller shown is btif_gatts_send_response_impl. The material does not show whether other paths exist.
- Only attr_value.len is clamped. attr_value.offset is still copied through unchanged and is not validated here. Whether downstream code checks it is not shown in the material.
- attp_build_value_cmd itself is not modified. The fix relies on the clamped len reaching it rather than adding a check at the consumer.
- The size of btgatt_response_t::attr_value.value relative to GATT_MAX_ATTR_LEN is not shown. The fix assumes the first len bytes of the source are valid.
Behavior changes
- A GATT server response whose attr_value.len exceeds GATT_MAX_ATTR_LEN is silently truncated to GATT_MAX_ATTR_LEN bytes rather than passed through with an oversized length.
- Bytes of p_dest->attr_value.value beyond the clamped len are no longer written by this function. Before the fix, all GATT_MAX_ATTR_LEN bytes were overwritten.
Per major
- Android 14: Same fix: commit 57b823f4f758 in android-security-14.0.0_r5 (cherry-pick of internal change Change-Id Iefa66f3a293ac2072ba79853a9ec23cdfe4c1368). At android-security-14.0.0_r29, 7/8 lines of the patched region are present. The material does not say which line differs.
- Android 15: Not affected per the bulletin. At android-security-15.0.0_r17, 7/8 lines of the patched region are present.
- Android 16: Not affected per the bulletin. At android-security-16.0.0_r8, 7/8 lines of the patched region are present.
- Android 17: Not affected per the bulletin. At android-security-17.0.0_r1, 7/8 lines of the patched region are present.
Unknowns
- The declared size of btgatt_response_t::attr_value.value and of tGATTS_RSP::attr_value.value. The material only states that the valid size depends on len.
- How attp_build_value_cmd uses attr_value.len and value. This is not shown in the diff or context.
- Which line differs in the 7/8 match at the latest security tags, and whether the clamped len and len-based memcpy lines are among the lines present.
- Whether the oversized length can come from a remote peer or only from a local caller of the GATT server API.