[PATCH 5.15.y 0/2] Bluetooth: L2CAP: fix connectionless receive path
From: Karl Mehltretter
Date: Thu Sep 17 2026 - 00:01:56 EST
5.15.y has two problems on the L2CAP connectionless receive path. The first
comes from a backport that landed without its prerequisite, the second from
a fix that never landed at all. Upstream contains both fixes.
1) c531e63871c0 ("Bluetooth: l2cap: always unlock channel in
l2cap_conless_channel()") was backported as 5caf0ffaf915 without
f1a8f402f13f ("Bluetooth: L2CAP: Fix deadlock"), which is what adds the
matching lock. l2cap_conless_channel() therefore calls
l2cap_chan_unlock() on a mutex it never acquired, and
l2cap_sock_recv_cb() runs with no chan->lock at all on that path.
Patch 1 applies the l2cap_core.c hunks of f1a8f402f13f, which supply
the lock.
2) 89e856e124f9 ("bluetooth/l2cap: sync sock recv cb and release") never
landed here, so l2cap_sock_recv_cb() has no NULL check on chan->data,
while l2cap_sock_destruct() still sets it to NULL. Closing a receiving
socket while L2CAP data is inbound gives lock_sock(NULL). Patch 2
restores that guard in the form the commit has after f1a8f402f13f, that
is without the channel locking that caused the recursive chan->lock
deadlock.
89e856e124f9 is the fix for CVE-2024-41062. It went to 6.1.101, 6.6.42,
6.9.11 and 6.10 in July 2024 and to 5.10.270 this month. 5.15.y has never
carried it.
On why patch 1 is only part of f1a8f402f13f: as posted, that patch touched
only net/bluetooth/l2cap_core.c and net/bluetooth/l2cap_sock.c.
https://lore.kernel.org/linux-bluetooth/20240624134637.3790278-1-luiz.dentz@xxxxxxxxx/
The hci_core.c, hci_sync.c and hci_sync.h changes in the merged commit come
from a separate patch that was squashed into it while the pull request was
prepared. The author noted this when the AUTOSEL backport came up in 2024
and said that for stable it would be better to unmerge them:
https://lore.kernel.org/linux-bluetooth/CABBYNZLzf2x6cScmjGv2Rxk-i3F9=QKVWosrSEBgmHBdHqOWtg@xxxxxxxxxxxxxx/
Of the two posted files, only the l2cap_core.c side applies here, because
l2cap_sock_recv_cb() in 5.15.y has no channel locking to remove.
Tested in QEMU with two virtual BR/EDR controllers, PROVE_LOCKING,
DEBUG_MUTEXES and KASAN. Three runs of each variant:
v5.15.221 as released bad unlock balance, and a fatal NULL dereference
in l2cap_sock_recv_cb() from hci_rx_work, 3/3
+ patch 1 unbalanced unlock gone, NULL deref remains 3/3
+ patch 1 and 2 clean 3/3 over 300 socket close cycles
BUG: kernel NULL pointer dereference, address: 000000000000008c
Workqueue: hci0 hci_rx_work
lock_sock_nested
l2cap_sock_recv_cb+0x36/0xf0
l2cap_recv_frame
BlueZ l2cap-tester, rfcomm-tester, smp-tester, bnep-tester, sco-tester and
hci-tester give identical results before and after.
Also on a Raspberry Pi 400 with a second board as the L2CAP peer, each test
from its own boot so lockdep was armed for each. The released kernel
reproduced the connectionless lockdep warning, and both it and the
patch-1-only kernel died under teardown stress. With both patches, 300
receiver close cycles against 25,877 peer datagram floods completed with no
warning and debug_locks still 1. Connected L2CAP and A2DP playback showed
no regression on any of the three. The hardware crashes left no readable
trace, so the attributed NULL dereference above is from QEMU.
The 5.10.y fix has a different shape and was sent separately as
20260916193454.9996-1-kmehltretter@xxxxxxxxx. That tree still has
89e856e124f9, so both L2CAP hunks of f1a8f402f13f apply there unchanged and
one patch covers it.
base-commit: 0248c33e835ecbec3a591f93fdaae53f7b90a4d6