Skip to content

Commit 64e3a83

Browse files
committed
vsock: Fix transport_* TOCTOU
jira VULN-80682 jira VULN-80681 cve CVE-2025-38461 commit-author Michal Luczaj <mhal@rbox.co> commit 687aa0c Transport assignment may race with module unload. Protect new_transport from becoming a stale pointer. This also takes care of an insecure call in vsock_use_local_transport(); add a lockdep assert. BUG: unable to handle page fault for address: fffffbfff8056000 Oops: Oops: 0000 [#1] SMP KASAN RIP: 0010:vsock_assign_transport+0x366/0x600 Call Trace: vsock_connect+0x59c/0xc40 __sys_connect+0xe8/0x100 __x64_sys_connect+0x6e/0xc0 do_syscall_64+0x92/0x1c0 entry_SYSCALL_64_after_hwframe+0x4b/0x53 Fixes: c0cfa2d ("vsock: add multi-transports support") Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> Signed-off-by: Michal Luczaj <mhal@rbox.co> Link: https://patch.msgid.link/20250703-vsock-transports-toctou-v4-2-98f0eb530747@rbox.co Signed-off-by: Jakub Kicinski <kuba@kernel.org> (cherry picked from commit 687aa0c) Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent 51deadb commit 64e3a83

File tree

1 file changed

+23
-5
lines changed

1 file changed

+23
-5
lines changed

net/vmw_vsock/af_vsock.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,8 @@ EXPORT_SYMBOL_GPL(vsock_enqueue_accept);
398398

399399
static bool vsock_use_local_transport(unsigned int remote_cid)
400400
{
401+
lockdep_assert_held(&vsock_register_mutex);
402+
401403
if (!transport_local)
402404
return false;
403405

@@ -455,6 +457,8 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
455457

456458
remote_flags = vsk->remote_addr.svm_flags;
457459

460+
mutex_lock(&vsock_register_mutex);
461+
458462
switch (sk->sk_type) {
459463
case SOCK_DGRAM:
460464
new_transport = transport_dgram;
@@ -469,12 +473,15 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
469473
new_transport = transport_h2g;
470474
break;
471475
default:
472-
return -ESOCKTNOSUPPORT;
476+
ret = -ESOCKTNOSUPPORT;
477+
goto err;
473478
}
474479

475480
if (vsk->transport) {
476-
if (vsk->transport == new_transport)
477-
return 0;
481+
if (vsk->transport == new_transport) {
482+
ret = 0;
483+
goto err;
484+
}
478485

479486
/* transport->release() must be called with sock lock acquired.
480487
* This path can only be taken during vsock_stream_connect(),
@@ -489,8 +496,16 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
489496
/* We increase the module refcnt to prevent the transport unloading
490497
* while there are open sockets assigned to it.
491498
*/
492-
if (!new_transport || !try_module_get(new_transport->module))
493-
return -ENODEV;
499+
if (!new_transport || !try_module_get(new_transport->module)) {
500+
ret = -ENODEV;
501+
goto err;
502+
}
503+
504+
/* It's safe to release the mutex after a successful try_module_get().
505+
* Whichever transport `new_transport` points at, it won't go away until
506+
* the last module_put() below or in vsock_deassign_transport().
507+
*/
508+
mutex_unlock(&vsock_register_mutex);
494509

495510
ret = new_transport->init(vsk, psk);
496511
if (ret) {
@@ -501,6 +516,9 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
501516
vsk->transport = new_transport;
502517

503518
return 0;
519+
err:
520+
mutex_unlock(&vsock_register_mutex);
521+
return ret;
504522
}
505523
EXPORT_SYMBOL_GPL(vsock_assign_transport);
506524

0 commit comments

Comments
 (0)