CVE-2024-43763 AI-generated analysis
platform/packages/modules/Bluetooth, GATT server (system/stack/gatt/gatt_sr.cc)
Changes the early-exit condition in build_read_multi_rsp (system/stack/gatt/gatt_sr.cc) so a zero-length attribute value is encoded into the GATT Read Multiple (Variable) response instead of terminating the response builder and producing a truncated or empty packet.
Root cause
In build_read_multi_rsp, for each requested handle the code computes len = std::min(p_rsp->attr_value.len, mtu - total_len) and then did `if (len == 0) break;` with a "Buffer space not enough" log. That condition mixes up two cases: the buffer really being full (mtu - total_len == 0) and the attribute simply having a zero-length value (attr_value.len == 0). A zero-length value is valid and, in variable-length mode, should still add its 2-byte length field (value 0) to the packet. Because the loop broke out instead, the response stopped at the first zero-length value. If the first characteristic had length 0, the commit message says an empty packet was returned (p_buf->len starts at 1, the opcode byte).
How the fix works
- system/stack/gatt/gatt_sr.cc:build_read_multi_rsp: the break condition `if (len == 0)` is replaced with `if (total_len == mtu && p_rsp->attr_value.len > 0)`. In the post-fix code, the earlier `if (total_len > mtu) break;` guarantees total_len <= mtu at this point. So the new condition fires only when the buffer is exactly full and the attribute has data that cannot fit.
- With the new condition, a zero-length attr_value falls through. In variable_len mode, UINT16_TO_STREAM writes a 2-byte length of 0 and p_buf->len += 2. ARRAY_TO_STREAM with len 0 appends no value bytes, and the loop moves on to the next handle.
- The overflow handling below is unchanged for non-zero values that only partly fit: len < attr_value.len sets is_overflow, the partial value is written, then the loop breaks.
Completeness
- The fix is limited to the single break condition in build_read_multi_rsp. The handle-mismatch path (GATT_NOT_FOUND) and the partial-fit overflow path are untouched.
- The same loop serves both variable-length and fixed-length Read Multiple; variable_len only controls the 2-byte length prefix. For fixed-length responses, a zero-length value now adds nothing and the loop continues.
- Nothing changes in how p_rsp entries are queued into multi_rsp_q or in the caller. The material does not show the surrounding request handling, so other response-building paths cannot be judged from it.
Behavior changes
- Read Multiple (Variable) responses now include a 2-byte length field of 0 for zero-length attribute values and continue to later handles, instead of stopping at the first zero-length value.
- The 'Buffer space not enough for this data item, skipping' verbose log at this check is now emitted only when the buffer is exactly full and the item has non-zero length.
Per major
- Android 14: same fix: ec76dc86a8e9 in android-security-14.0.0_r15 (cherry-picked from ba907afffe1f, Change-Id Ida4f6b566cf9fa40fc5330d8084c29669ccaa608). One-line condition change, using VLOG(1). Patched region fully present at android-security-14.0.0_r29 (2/2 lines).
- Android 15: same fix: 124c2ac6cffb in android-security-15.0.0_r3. Identical condition change, using log::verbose instead of VLOG(1). Patched region fully present at android-security-15.0.0_r17 (2/2 lines).
- Android 16: not affected per the bulletin. 0/2 lines of the patched region present at android-security-16.0.0_r8; the material does not show the code there.
- Android 17: not affected per the bulletin. 0/2 lines of the patched region present at android-security-17.0.0_r1; the material does not show the code there.
Unknowns
- How a truncated or empty response leads to the DoS described by the bulletin (which side fails and how) is not shown in the material.
- The transport and request dispatch path that reaches build_read_multi_rsp are not shown.
- The state of build_read_multi_rsp on Android 16/17 (why 0/2 lines match) is not shown. The bulletin lists only 12 through 15-next as affected.
- The second bug id (356886209) is referenced but its content is not in the material.