Bluetooth: RFCOMM: serialize security confirmation handling
authorChengfeng Ye <nicoyip.dev@gmail.com>
Sat, 22 Aug 2026 16:43:41 +0000 (00:43 +0800)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Mon, 24 Aug 2026 17:13:36 +0000 (13:13 -0400)
rfcomm_security_cfm() looks up a session on session_list and then walks
its DLC list without holding rfcomm_mutex. Since RFCOMM session teardown
uses rfcomm_mutex, krfcommd can close and free the same session and DLCs
concurrently:

  hci_rx_work                    krfcommd
  -----------                    ---------
  rfcomm_session_get()
                                 rfcomm_lock()
                                 rfcomm_session_close()
                                   rfcomm_dlc_unlink()
                                   rfcomm_session_del()
                                     kfree(s)
                                 rfcomm_unlock()
  walk s->dlcs

The callback can then read a freed session list head and touch freed DLCs
while updating their flags or timers.

Serialize the session lookup and DLC traversal in rfcomm_security_cfm()
with rfcomm_mutex. This matches the existing RFCOMM session lifetime
rules and prevents concurrent rfcomm_session_del() / rfcomm_dlc_unlink()
from tearing the objects down while the callback is using them.

KASAN reported:

  BUG: KASAN: slab-use-after-free in rfcomm_security_cfm+0x41c/0x440
  Read of size 8 at addr ffff888111fb3960 by task kworker/u17:1/89
  Workqueue: hci0 hci_rx_work
  Call Trace:
   rfcomm_security_cfm+0x41c/0x440
   hci_encrypt_cfm+0x139/0x590
   hci_encrypt_change_evt+0x37b/0xc40
   hci_event_packet+0x71b/0xb20
   hci_rx_work+0x293/0x730
  Allocated by task 69:
   rfcomm_session_add+0x9e/0x2f0
   rfcomm_run+0x44b/0x41e0
  Freed by task 69:
   kfree+0x131/0x3c0
   rfcomm_session_del+0x188/0x220
   rfcomm_run+0x1985/0x41e0

Fixes: 08c30aca9e698faddebd34f81e1196295f9dc063 ("Bluetooth: Remove RFCOMM session refcnt")
Cc: stable@vger.kernel.org
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
net/bluetooth/rfcomm/core.c

index 0e496b8..63fa0f5 100644 (file)
@@ -2217,9 +2217,13 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
 
        BT_DBG("conn %p status 0x%02x encrypt 0x%02x", conn, status, encrypt);
 
+       rfcomm_lock();
+
        s = rfcomm_session_get(&conn->hdev->bdaddr, &conn->dst);
-       if (!s)
+       if (!s) {
+               rfcomm_unlock();
                return;
+       }
 
        list_for_each_entry_safe(d, n, &s->dlcs, list) {
                if (test_and_clear_bit(RFCOMM_SEC_PENDING, &d->flags)) {
@@ -2251,6 +2255,8 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
                        set_bit(RFCOMM_AUTH_REJECT, &d->flags);
        }
 
+       rfcomm_unlock();
+
        rfcomm_schedule();
 }