[BUG] Bluetooth: SCO: UAF due to concurrent sco_sock_connect() on same socket

From: Cen Zhang
Date: Sat Nov 01 2025 - 10:40:51 EST


Hi maintainers,

I would like to report a KASAN use-after-free in the SCO path caused by two concurrent sco_sock_connect() calls on the same socket.
This race allows both call paths to proceed into sco_connect() and eventually bind two different struct sco_conn objects to the same sk.
Later, when sk->conn has been updated to the second conn, close() can free that conn and the socket,
while the HCI connect-confirm path still references the first (stale) conn/sk, triggering a UAF.

Thread 1: Thread 2: Thread3:
check sk_state check sk_state
sco_sock_connect(sk) sco_sock_connect(sk) sco_connect_cfm(sk->conn)
conn1->sk = sk
conn2->sk = sk
sk->conn = conn1
sk->conn = conn2
sco_sock_release
free conn2 and sk
sco_connect_cfm
sco_conn_del
sco_conn_free
UAF on sk

Representative KASAN excerpt

BUG: KASAN: slab-use-after-free in sco_conn_free net/bluetooth/sco.c:94
Write of size 8 at addr ffff88810d2be350 by task kworker/u25:1/88
Call Trace:
sco_conn_free net/bluetooth/sco.c:94 [inline]
kref_put include/linux/kref.h:65 [inline]
sco_conn_put+0x49d/0xfc0 net/bluetooth/sco.c:115
sco_conn_del+0x46d/0x8d0 net/bluetooth/sco.c:280
sco_connect_cfm+0x83d/0x1ee0 net/bluetooth/sco.c:1468
hci_connect_cfm include/net/bluetooth/hci_core.h:2082 [inline]
Allocated by task 294:
sco_sock_create+0x22d/0xc00 net/bluetooth/sco.c:616
Freed by task 295:
__sk_destruct+0x4b0/0x630 net/core/sock.c:2373
sock_put include/net/sock.h:1962 [inline]
sco_sock_kill+0x64d/0x9b0 net/bluetooth/sco.c:526
sco_sock_release+0x770/0xa50 net/bluetooth/sco.c:1359

Reproducer and race amplification

- A easy PoC which triggers concurrent sco_sock_connect() on the same socket and a fast close is available here:
https://github.com/zzzcccyyyggg/Syzkaller-log/blob/main/UAF-in-sco_conn_free-due-to-concurrent-sco_sock_connect/poc.c

- To enlarge the probability that two connect operations overlap (i.e., widen the race window), inserting a fixed delay right after the state/type checks reliably reproduces the issue in my tests. Concretely, after:

if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
release_sock(sk);
return -EBADFD;
}

if (sk->sk_type != SOCK_SEQPACKET) {
release_sock(sk);
return -EINVAL;
}

add:

/* increase race window for testing */
msleep(2000);


We tried using the following patch to fix this bug, but it seems to have failed.
https://lore.kernel.org/linux-bluetooth/20251101104522.174388-1-zzzccc427@xxxxxxx/T/#t

Thank you for your attention to this matter.

Best regards,
Cen Zhang