]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Bluetooth: SCO: Fix use-after-free in sco_recv_frame() due to missing sock_hold
authorHyunwoo Kim <imv4bel@gmail.com>
Thu, 12 Mar 2026 20:26:16 +0000 (05:26 +0900)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Thu, 19 Mar 2026 18:42:35 +0000 (14:42 -0400)
sco_recv_frame() reads conn->sk under sco_conn_lock() but immediately
releases the lock without holding a reference to the socket. A concurrent
close() can free the socket between the lock release and the subsequent
sk->sk_state access, resulting in a use-after-free.

Other functions in the same file (sco_sock_timeout(), sco_conn_del())
correctly use sco_sock_hold() to safely hold a reference under the lock.

Fix by using sco_sock_hold() to take a reference before releasing the
lock, and adding sock_put() on all exit paths.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
net/bluetooth/sco.c

index e7db50165879c54a6318f3aa703c7e51a31dfa3c..584e059de20a660e6ea5704466bf8df3dfdc6cec 100644 (file)
@@ -401,7 +401,7 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
        struct sock *sk;
 
        sco_conn_lock(conn);
-       sk = conn->sk;
+       sk = sco_sock_hold(conn);
        sco_conn_unlock(conn);
 
        if (!sk)
@@ -410,11 +410,15 @@ static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
        BT_DBG("sk %p len %u", sk, skb->len);
 
        if (sk->sk_state != BT_CONNECTED)
-               goto drop;
+               goto drop_put;
 
-       if (!sock_queue_rcv_skb(sk, skb))
+       if (!sock_queue_rcv_skb(sk, skb)) {
+               sock_put(sk);
                return;
+       }
 
+drop_put:
+       sock_put(sk);
 drop:
        kfree_skb(skb);
 }