Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access
Overview
| CVE | CVE-2026-31393 |
| Component | net/bluetooth/l2cap_core.c (l2cap_information_rsp()) |
| Attack surface | Bluetooth BR/EDR L2CAP signalling during capability discovery |
| Fixed | Linux v6.14 (4b0c8bb9885a) |
| Class | CWE-125 (Out-of-Bounds Read) |
| CVSS v3.1 | 8.1 (High, kernel.org CNA) -- CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H |
| Found and patched by | Lukas Johannes Moeller (@JohannesLks) |
TL;DR
l2cap_information_rsp() validates the 4-byte L2CAP_INFO_RSP header, then reads optional response payload fields without proving those bytes are present. A nearby device can send a truncated success response and make the kernel read past the received command buffer before pairing or authentication.
Root Cause
The handler first ensures the fixed response header exists:
if (cmd_len < sizeof(struct l2cap_info_rsp))
return -EPROTO;
That is sufficient for type and result, but not for the data interpreted after a successful response:
case L2CAP_IT_FEAT_MASK:
conn->feat_mask = get_unaligned_le32(rsp->data);
break;
case L2CAP_IT_FIXED_CHAN:
if (rsp->data[0] & L2CAP_FC_SIG_BREDR)
...
The missing invariant is per-response minimum length: FEAT_MASK needs 8 total command bytes, while FIXED_CHAN needs at least 5.
Impact
- Triggerable by a Bluetooth peer within radio range during L2CAP setup.
- Observed security property: kernel heap out-of-bounds read into parser state, not a demonstrated controlled leak to userspace.
- Practical impact is conservative: memory-safety bug in pre-pairing Bluetooth parsing, fixed upstream; no code execution primitive claimed.
Fix
The fix adds payload-length checks at the point where each optional field is read:
case L2CAP_IT_FEAT_MASK:
if (cmd_len >= 8)
conn->feat_mask = get_unaligned_le32(rsp->data);
break;
case L2CAP_IT_FIXED_CHAN:
if (cmd_len >= 5 && (rsp->data[0] & L2CAP_FC_SIG_BREDR))
...