PT-2026-121986
CVE-2026-99009
·
Published
2026-10-23
·
Updated
2026-10-23
Description by
Score
N/A
Not availableNo severity ratings or metrics are available. When they are, we'll update the corresponding info on the page.
In the Linux kernel, the following vulnerability has been resolved:
Bluetooth: RFCOMM: connect the session socket without rfcomm mutex
An RFCOMM connect() issued while a BR/EDR link is being authenticated
makes lockdep report a circular dependency, and the reported cycle is a
real AB/BA between rfcomm mutex and hdev->lock.
rfcomm security cfm() is called from the HCI event path, which already
holds hdev->lock:
hci rx work()
hci event packet()
hci cc read enc key size() [hdev->lock]
hci encrypt cfm() [hci cb list lock]
rfcomm security cfm() [rfcomm mutex]
while an RFCOMM connect() from userspace takes the same two locks the
other way round:
rfcomm sock connect()
rfcomm dlc open() [rfcomm mutex]
rfcomm dlc open()
rfcomm session create()
kernel connect()
l2cap sock connect()
l2cap chan connect() [hdev->lock]
WARNING: possible circular locking dependency detected
kworker/u131:1/1128 is trying to acquire lock:
rfcomm mutex, at: rfcomm security cfm+0x31/0x3e0 [rfcomm]
but task is already holding lock:
hci cb list lock, at: hci cc read enc key size+0x1d2/0xcc0
Chain exists of:
rfcomm mutex --> &hdev->lock --> hci cb list lock
hci auth complete evt() and hci encrypt change evt() reach the callback
the same way.
Both orders have to be seen in the same boot, which is why a BR/EDR
connection alone is not enough to show it: a session set up by the
remote side is created by rfcomm accept connection() in krfcommd, which
calls kernel accept() and never takes hdev->lock under rfcomm mutex.
Connecting a device that authenticates and encrypts the link and then
calling connect() on an RFCOMM socket towards any address - the connect
does not have to succeed, the order is recorded before the page timeout
- reports it every time.
Only the session socket has to be connected with the lock held, and it
does not: nothing else can see the socket before it is put on the
session list. So connect it first and take rfcomm mutex afterwards,
which removes the rfcomm mutex -> hdev->lock order for good, rather
than keeping the HCI event path out of rfcomm mutex.
rfcomm session create() becomes rfcomm session connect(), which returns
the connected socket without touching the session list, and
rfcomm dlc open() adds the session once it holds the lock again. If
another opener added a session for the same pair while this socket was
connecting, that session is used and this socket is dropped.
rfcomm dlc open() now takes the session it should use, and its state
check runs after the lock is re-acquired, so a DLC that was opened or
closed in the meantime is still handled.
Over an existing ACL link the connection can complete before the
session reaches the list, and the wakeup from the socket callback is
then lost, so krfcommd is woken once the session is visible.
Connecting without the lock opens a window in which the socket can be
closed. The DLC is not on a session yet, so rfcomm dlc close() finds
nothing to do and returns without touching it, and rfcomm dlc open()
would then attach a DLC whose owner is gone. rfcomm dlc close() now
marks such a DLC with RFCOMM CLOSED, and rfcomm dlc open() checks the
mark once it holds rfcomm mutex again and drops the socket instead of
attaching the DLC. The mark is cleared when an open starts, so a DLC
that is reused is not affected. This covers both callers of
rfcomm dlc open(), the socket and the tty layer.
Found an issue in the description? Have something to add? Feel free to write us 👾