mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
Bluetooth: RFCOMM: serialize security confirmation handling
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: 08c30aca9e ("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>
This commit is contained in:
parent
ca0583c246
commit
759c185d0b
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user