Thread (13 messages) 13 messages, 3 authors, 2025-11-17

Re: [syzbot] [virt?] [net?] possible deadlock in vsock_linger

From: Stefano Garzarella <sgarzare@redhat.com>
Date: 2025-10-21 10:09:38
Also in: lkml, virtualization

On Mon, Oct 20, 2025 at 05:02:56PM -0700, syzbot wrote:
Hello,

syzbot found the following issue on:

HEAD commit:    d9043c79ba68 Merge tag 'sched_urgent_for_v6.18_rc2' of git..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=130983cd980000
kernel config:  https://syzkaller.appspot.com/x/.config?x=f3e7b5a3627a90dd
dashboard link: https://syzkaller.appspot.com/bug?extid=10e35716f8e4929681fa
compiler:       gcc (Debian 12.2.0-14+deb12u1) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=17f0f52f980000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=11ea9734580000
#syz test
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -565,6 +565,11 @@ static u32 vsock_registered_transport_cid(const struct vsock_transport **transpo
         return cid;
  }

+/* vsock_find_cid() must be called outside lock_sock/release_sock
+ * section to avoid a potential lock inversion deadlock with
+ * vsock_assign_transport() where `vsock_register_mutex` is taken when
+ * `sk_lock-AF_VSOCK` is already held.
+ */
  bool vsock_find_cid(unsigned int cid)
  {
         if (cid == vsock_registered_transport_cid(&transport_g2h))
@@ -735,23 +740,14 @@ static int __vsock_bind_dgram(struct vsock_sock *vsk,
         return vsk->transport->dgram_bind(vsk, addr);
  }

+/* The caller must ensure the socket is not already bound and provide a valid
+ * `addr` to bind (VMADDR_CID_ANY, or a CID assgined to a transport).
+ */
  static int __vsock_bind(struct sock *sk, struct sockaddr_vm *addr)
  {
         struct vsock_sock *vsk = vsock_sk(sk);
         int retval;

-       /* First ensure this socket isn't already bound. */
-       if (vsock_addr_bound(&vsk->local_addr))
-               return -EINVAL;
-
-       /* Now bind to the provided address or select appropriate values if
-        * none are provided (VMADDR_CID_ANY and VMADDR_PORT_ANY).  Note that
-        * like AF_INET prevents binding to a non-local IP address (in most
-        * cases), we only allow binding to a local CID.
-        */
-       if (addr->svm_cid != VMADDR_CID_ANY && !vsock_find_cid(addr->svm_cid))
-               return -EADDRNOTAVAIL;
-
         switch (sk->sk_socket->type) {
         case SOCK_STREAM:
         case SOCK_SEQPACKET:
@@ -991,15 +987,33 @@ vsock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
  {
         int err;
         struct sock *sk;
+       struct vsock_sock *vsk;
         struct sockaddr_vm *vm_addr;

         sk = sock->sk;
+       vsk = vsock_sk(sk);

         if (vsock_addr_cast(addr, addr_len, &vm_addr) != 0)
                 return -EINVAL;

+       /* Like AF_INET prevents binding to a non-local IP address (in most
+        * cases), we only allow binding to a local CID.
+        */
+       if (vm_addr->svm_cid != VMADDR_CID_ANY &&
+           !vsock_find_cid(vm_addr->svm_cid))
+               return -EADDRNOTAVAIL;
+
         lock_sock(sk);
+
+       /* Ensure this socket isn't already bound. */
+       if (vsock_addr_bound(&vsk->local_addr)) {
+               err = -EINVAL;
+               goto out;
+       }
+
         err = __vsock_bind(sk, vm_addr);
+
+out:
         release_sock(sk);

         return err;
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help