Skip to content

Commit c0b3e1b

Browse files
committed
vsock: fix lock inversion in vsock_assign_transport()
jira VULN-80682 jira VULN-80681 cve-bf CVE-2025-38461 commit-author Michal Luczaj <mhal@rbox.co> commit f7c877e upstream-diff | Adjusted context due to missing SEQPACKET support Syzbot reported a potential lock inversion deadlock between vsock_register_mutex and sk_lock-AF_VSOCK when vsock_linger() is called. The issue was introduced by commit 687aa0c ("vsock: Fix transport_* TOCTOU") which added vsock_register_mutex locking in vsock_assign_transport() around the transport->release() call, that can call vsock_linger(). vsock_assign_transport() can be called with sk_lock held. vsock_linger() calls sk_wait_event() that temporarily releases and re-acquires sk_lock. During this window, if another thread hold vsock_register_mutex while trying to acquire sk_lock, a circular dependency is created. Fix this by releasing vsock_register_mutex before calling transport->release() and vsock_deassign_transport(). This is safe because we don't need to hold vsock_register_mutex while releasing the old transport, and we ensure the new transport won't disappear by obtaining a module reference first via try_module_get(). Reported-by: syzbot+10e35716f8e4929681fa@syzkaller.appspotmail.com Tested-by: syzbot+10e35716f8e4929681fa@syzkaller.appspotmail.com Fixes: 687aa0c ("vsock: Fix transport_* TOCTOU") Cc: mhal@rbox.co Cc: stable@vger.kernel.org Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> Link: https://patch.msgid.link/20251021121718.137668-1-sgarzare@redhat.com Signed-off-by: Paolo Abeni <pabeni@redhat.com> (cherry picked from commit f7c877e) Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
1 parent 02a4893 commit c0b3e1b

File tree

1 file changed

+19
-19
lines changed

1 file changed

+19
-19
lines changed

net/vmw_vsock/af_vsock.c

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -477,12 +477,26 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
477477
goto err;
478478
}
479479

480-
if (vsk->transport) {
481-
if (vsk->transport == new_transport) {
482-
ret = 0;
483-
goto err;
484-
}
480+
if (vsk->transport && vsk->transport == new_transport) {
481+
ret = 0;
482+
goto err;
483+
}
485484

485+
/* We increase the module refcnt to prevent the transport unloading
486+
* while there are open sockets assigned to it.
487+
*/
488+
if (!new_transport || !try_module_get(new_transport->module)) {
489+
ret = -ENODEV;
490+
goto err;
491+
}
492+
493+
/* It's safe to release the mutex after a successful try_module_get().
494+
* Whichever transport `new_transport` points at, it won't go away until
495+
* the last module_put() below or in vsock_deassign_transport().
496+
*/
497+
mutex_unlock(&vsock_register_mutex);
498+
499+
if (vsk->transport) {
486500
/* transport->release() must be called with sock lock acquired.
487501
* This path can only be taken during vsock_stream_connect(),
488502
* where we have already held the sock lock.
@@ -502,20 +516,6 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
502516
vsk->peer_shutdown = 0;
503517
}
504518

505-
/* We increase the module refcnt to prevent the transport unloading
506-
* while there are open sockets assigned to it.
507-
*/
508-
if (!new_transport || !try_module_get(new_transport->module)) {
509-
ret = -ENODEV;
510-
goto err;
511-
}
512-
513-
/* It's safe to release the mutex after a successful try_module_get().
514-
* Whichever transport `new_transport` points at, it won't go away until
515-
* the last module_put() below or in vsock_deassign_transport().
516-
*/
517-
mutex_unlock(&vsock_register_mutex);
518-
519519
ret = new_transport->init(vsk, psk);
520520
if (ret) {
521521
module_put(new_transport->module);

0 commit comments

Comments
 (0)