CVE-2026-80819: Bluetooth: RFCOMM: take rfcomm_mutex for the deferred setup accept
In the Linux kernel, the following vulnerability has been resolved:
Bluetooth: RFCOMM: take rfcommmutex for the deferred setup accept
rfcommsockrecvmsg() completes a deferred setup by calling rfcommdlcaccept() without holding any RFCOMM lock:
if (testandclearbit(RFCOMMDEFERSETUP, &d->flags)) { rfcommdlcaccept(d); return 0; }
and rfcommdlcaccept() dereferences the session on its first line:
struct sock sk = d->session->sock->sk;
Every other path that touches d->session runs under rfcommmutex: rfcommdlcopen(), rfcommdlcclose(), rfcommdlcexists(), rfcommdlcsendrpn(), and the RFCOMM thread through rfcommprocesssessions(). rfcommconnectind() is even documented as "called under rfcommlock()". This call site is the only one that skips it.
The RFCOMMDEFERSETUP bit looks like it serialises the accept against teardown, since rfcommdlcclose() returns early when it wins the testandclear. But rfcommrecvdisc() forces the state first:
d->state = BTCLOSED; rfcommdlcclose(d, err);
and the early return only covers BTCONNECT, BTCONFIG, BTOPEN and BTCONNECT2. With the state already BTCLOSED that switch does not match, the bit is never consulted, and rfcommdlcclose() falls through to rfcommdlcunlink(), which sets d->session = NULL.
So a remote DISC on a deferred dlc clears the session while leaving RFCOMMDEFERSETUP set. The next recvmsg() then passes the testandclear and dereferences a NULL session. No timing window is needed: once the DISC has been processed, the dereference is unconditional.
Give rfcommdlcaccept() the same shape as rfcommdlcopen() and rfcommdlcclose(): an exported wrapper that takes rfcommmutex and re-checks the session, around a rfcommdlcaccept() that the two in-core callers, which already hold the mutex, keep using.
Reproduced on a KASAN + PROVELOCKING kernel with a BR/EDR peer emulated over /dev/vhci: the peer brings up an ACL link, opens L2CAP on the RFCOMM PSM, starts a session, opens a dlc on a channel bound with BTDEFERSETUP, and sends DISC after the socket is accepted. recv() on the accepted socket then hits:
Oops: general protection fault KASAN: null-ptr-deref in range [0x0000000000000010-0x0000000000000017] RIP: 0010:rfcommdlcaccept+0x54/0x350 Call Trace: rfcommsockrecvmsg+0x1cd/0x230 sockrecvmsg+0x166/0x1c0 sysrecvfrom+0x20d/0x300
0x10 is the offset of sock in struct rfcommsession. With this patch the same run completes with recv() returning 0 and no report, and lockdep stays quiet, confirming rfcommmutex is still taken before locksock on this path as it is on the thread side.
Event History
Frequently Asked Questions
What conditions are needed to trigger the race?
The RFCOMM socket must use deferred setup, and a receive operation must complete that setup while a disconnect or teardown path concurrently closes the RFCOMM session. The vulnerable path calls rfcomm_dlc_accept() without holding rfcomm_mutex while teardown can invalidate the session it dereferences.
What is the likely impact if the race occurs?
The deferred setup accept path can dereference d->session after concurrent teardown. This can result in a kernel memory-safety failure; the provided data does not specify a more precise impact.
How can I determine whether my kernel includes the fix?
Check whether your kernel incorporates one of the referenced stable commits: d8d686dd5662a7c4745e4515f1237a9f3b7df181, eb71d5a1ea8ff2683e394b48ae3cd676037ab4c2, or 56f0aa75c7640e46397ef73bea251fcbef9150c0. The fix ensures the deferred setup accept path takes rfcomm_mutex before calling rfcomm_dlc_accept().