[PATCH 03/16] Bluetooth: L2CAP: fix race condition in l2cap_sock_shutdown()

From: Pauli Virtanen

Date: Sat Aug 29 2026 - 10:22:42 EST


l2cap_sock_shutdown() has the race condition

[Task 1] [Task 2]
l2cap_sock_shutdown l2cap_sock_connect
l2cap_chan_lock l2cap_chan_connect
conn = ... /* == NULL*/
l2cap_chan_unlock ------------> l2cap_chan_lock
if (conn) /* false */
__l2cap_chan_add(conn, chan)
l2cap_chan_lock <-------------- l2cap_chan_unlock
l2cap_chan_close /* chan->conn->lock not held! */

conn->lock protects conn->chan_l and is not properly held here.

Use the l2cap_chan_close_unlocked() helper that ensures conn->lock is
held for l2cap_chan_close().

Fixes: ab4eedb790ca ("Bluetooth: L2CAP: Fix corrupted list in hci_chan_del")
Reported-by: Eulgyu Kim <eulgyukim@xxxxxxxxx>
Reported-by: Jaeyoung Chung <jjy600901@xxxxxxxxx>
Link: https://lore.kernel.org/linux-bluetooth/20260824153908.2327306-1-jjy600901@xxxxxxxxx/
Link: https://syzkaller.appspot.com/bug?extid=0e4ebcc970728e056324
Signed-off-by: Pauli Virtanen <pav@xxxxxx>
---
net/bluetooth/l2cap_sock.c | 19 +------------------
1 file changed, 1 insertion(+), 18 deletions(-)

diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index b553b6356af8..0265b6508682 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1406,7 +1406,6 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
struct l2cap_chan *chan;
- struct l2cap_conn *conn;
int err = 0;

BT_DBG("sock %p, sk %p, how %d", sock, sk, how);
@@ -1463,23 +1462,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
sk->sk_shutdown |= SEND_SHUTDOWN;
release_sock(sk);

- l2cap_chan_lock(chan);
- /* prevent conn structure from being freed */
- conn = l2cap_conn_hold_unless_zero(chan->conn);
- l2cap_chan_unlock(chan);
-
- if (conn)
- /* mutex lock must be taken before l2cap_chan_lock() */
- mutex_lock(&conn->lock);
-
- l2cap_chan_lock(chan);
- l2cap_chan_close(chan, 0);
- l2cap_chan_unlock(chan);
-
- if (conn) {
- mutex_unlock(&conn->lock);
- l2cap_conn_put(conn);
- }
+ l2cap_chan_close_unlocked(chan, 0);

lock_sock(sk);

--
2.55.0