Bluetooth: hci_sock: purge socket queues in the destruct() callback
authorNguyen Dinh Phi <phind.uet@gmail.com>
Thu, 7 Oct 2021 19:04:24 +0000 (03:04 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 11 Mar 2023 12:57:39 +0000 (13:57 +0100)
commit 709fca500067524381e28a5f481882930eebac88 upstream.

The receive path may take the socket right before hci_sock_release(),
but it may enqueue the packets to the socket queues after the call to
skb_queue_purge(), therefore the socket can be destroyed without clear
its queues completely.

Moving these skb_queue_purge() to the hci_sock_destruct() will fix this
issue, because nothing is referencing the socket at this point.

Signed-off-by: Nguyen Dinh Phi <phind.uet@gmail.com>
Reported-by: syzbot+4c4ffd1e1094dae61035@syzkaller.appspotmail.com
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/bluetooth/hci_sock.c

index f1128c2134f027ecc701f77ce48929983bae8c50..3f92a21cabe8e876ad4f53919352c08a04dd3179 100644 (file)
@@ -888,10 +888,6 @@ static int hci_sock_release(struct socket *sock)
        }
 
        sock_orphan(sk);
-
-       skb_queue_purge(&sk->sk_receive_queue);
-       skb_queue_purge(&sk->sk_write_queue);
-
        release_sock(sk);
        sock_put(sk);
        return 0;
@@ -2012,6 +2008,12 @@ done:
        return err;
 }
 
+static void hci_sock_destruct(struct sock *sk)
+{
+       skb_queue_purge(&sk->sk_receive_queue);
+       skb_queue_purge(&sk->sk_write_queue);
+}
+
 static const struct proto_ops hci_sock_ops = {
        .family         = PF_BLUETOOTH,
        .owner          = THIS_MODULE,
@@ -2065,6 +2067,7 @@ static int hci_sock_create(struct net *net, struct socket *sock, int protocol,
 
        sock->state = SS_UNCONNECTED;
        sk->sk_state = BT_OPEN;
+       sk->sk_destruct = hci_sock_destruct;
 
        bt_sock_link(&hci_sk_list, sk);
        return 0;