Linux Kernel Remote Bluetooth vulns

Bluetooth L2CAP Vulnerabilities — Linux 6.6 LTS

Audited: net/bluetooth/l2cap_core.c on kernel 6.6.129
Status: CODE CONFIRMED (2 bugs), QEMU trigger WIP

BUG 1: Use-After-Free in l2cap_le_connect_rsp (CVE-2022-42896 variant)

File: net/bluetooth/l2cap_core.c
Function: l2cap_le_connect_rsp()
Line: 4695
Type: Use-After-Free
Remote: YES — zero-click, over BLE, no pairing required
Impact: Kernel code execution

Description: l2cap_le_connect_rsp() retrieves an L2CAP channel by identifier WITHOUT holding a reference:

    chan = __l2cap_get_chan_by_ident(conn, cmd->ident);  // line 4695
    // NO l2cap_chan_hold_unless_zero() here!
    l2cap_chan_lock(chan);  // UAF: chan can be freed before this
    ...
    l2cap_chan_unlock(chan);
    return err;            // never calls l2cap_chan_put()

Compare with l2cap_connect_create_rsp() which was FIXED for CVE-2022-42896 (commit 711f8c3fb3db):

chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
chan = l2cap_chan_hold_unless_zero(chan);  // ← HOLDS REFERENCE
l2cap_chan_lock(chan);
...
l2cap_chan_unlock(chan);
l2cap_chan_put(chan);                      // ← RELEASES REFERENCE

The LE (Low Energy) path was missed during the CVE-2022-42896 fix. Exact same bug pattern, different function.

Race scenario:

  Thread A (BT softirq):               Thread B (process context):
                                        close(bt_socket)
                                          → l2cap_chan_del → frees chan
  l2cap_le_connect_rsp():
    chan = __l2cap_get_chan_by_ident()   ← gets FREED pointer
    l2cap_chan_lock(chan)                ← UAF / crash

Attack vector: Attacker within Bluetooth range sends a crafted L2CAP LE Connection Response while the victim has a BLE socket being closed. No pairing or user interaction required. Works against any device with BLE enabled (Android phones, laptops, IoT).

On Android: BLE is always active when Bluetooth is on (for Google Pay, Find My Device, nearby share, etc).

Trigger approach (from GHSA-pf87-6c9q-jvm4 advisory pattern): 1. Establish BLE connection to victim 2. Send L2CAP LE Connection Request 3. Rapidly disconnect/reconnect to create socket churn 4. Time the L2CAP LE Connection Response to race with teardown

Affected:

  • Linux 6.6 LTS: CONFIRMED in source
  • Linux mainline: likely affected (function at same offset)
  • Android (android15-6.6, android16-6.12): likely affected
  • Any kernel after CVE-2022-42896 fix that has the LE path

BUG 2: Out-of-Bounds Read in l2cap_information_rsp

File: net/bluetooth/l2cap_core.c
Function: l2cap_information_rsp()
Lines: 4562, 4588, 4607
Type: Heap OOB read (info leak)
Remote: YES — over BR/EDR Bluetooth, pre-authentication
Impact: Kernel heap info leak

Description: l2cap_information_rsp() validates only the fixed header size:

    struct l2cap_info_rsp {
        __le16 type;      // 2 bytes
        __le16 result;    // 2 bytes
        __u8   data[];    // flexible array — 0 in sizeof
    };

    if (cmd_len < sizeof(*rsp))    // only checks >= 4 bytes!
        return -EPROTO;

Then accesses the flexible array WITHOUT checking data is present:

    case L2CAP_IT_FEAT_MASK:
        conn->feat_mask = get_unaligned_le32(rsp->data);  // reads 4 bytes OOB!

    case L2CAP_IT_FIXED_CHAN:
        conn->remote_fixed_chan = rsp->data[0];            // reads 1 byte OOB!

An attacker sends L2CAP_INFO_RSP with cmd_len=4 (header only, no data). The check at line 4562 passes. get_unaligned_le32(rsp->data) reads 4 bytes past the packet boundary into adjacent skb heap data.

The leaked value is stored in conn->feat_mask which influences subsequent L2CAP behavior (whether fixed channels are used). This is an info leak similar to CVE-2020-12352 (BadChoice from BleedingTooth).

Attack vector: Attacker within Bluetooth range sends a malformed L2CAP Information Response during connection setup. This happens BEFORE authentication — the info exchange is part of the L2CAP signaling that occurs immediately after ACL connection establishment.

No pairing, no user interaction. Single packet trigger, no race condition needed.

Affected:

  • Linux 6.6 LTS: CONFIRMED in source
  • Likely all kernel versions — this code hasn’t changed significantly

ADDITIONAL NOTE: l2cap_ecred_reconf_req missing refcount

File: net/bluetooth/l2cap_core.c
Function: l2cap_ecred_reconf_req()
Lines: 5325, 5357
Type: Potential UAF (lower severity)

Channels retrieved via __l2cap_get_chan_by_dcid() at line 5325 are stored in a local array and accessed at lines 5357-5358 WITHOUT reference counting. If a channel is freed between the two loops, the second loop accesses freed memory.

Lower severity because both loops run under conn->lock, reducing the race window. But a concurrent HCI disconnect event processed on another CPU could still trigger it.