Skip to content

Commit f7a66a7

Browse files
committed
vsock: Fix transport_* TOCTOU
jira VULN-80684 cve CVE-2025-38461 commit-author Michal Luczaj <[email protected]> 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 <[email protected]> Signed-off-by: Michal Luczaj <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> (cherry picked from commit 687aa0c) Signed-off-by: Brett Mastbergen <[email protected]>
1 parent 194aacb commit f7a66a7

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
@@ -399,6 +399,8 @@ EXPORT_SYMBOL_GPL(vsock_enqueue_accept);
399399

400400
static bool vsock_use_local_transport(unsigned int remote_cid)
401401
{
402+
lockdep_assert_held(&vsock_register_mutex);
403+
402404
if (!transport_local)
403405
return false;
404406

@@ -456,6 +458,8 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
456458

457459
remote_flags = vsk->remote_addr.svm_flags;
458460

461+
mutex_lock(&vsock_register_mutex);
462+
459463
switch (sk->sk_type) {
460464
case SOCK_DGRAM:
461465
new_transport = transport_dgram;
@@ -471,12 +475,15 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
471475
new_transport = transport_h2g;
472476
break;
473477
default:
474-
return -ESOCKTNOSUPPORT;
478+
ret = -ESOCKTNOSUPPORT;
479+
goto err;
475480
}
476481

477482
if (vsk->transport) {
478-
if (vsk->transport == new_transport)
479-
return 0;
483+
if (vsk->transport == new_transport) {
484+
ret = 0;
485+
goto err;
486+
}
480487

481488
/* transport->release() must be called with sock lock acquired.
482489
* This path can only be taken during vsock_connect(), where we
@@ -491,8 +498,16 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
491498
/* We increase the module refcnt to prevent the transport unloading
492499
* while there are open sockets assigned to it.
493500
*/
494-
if (!new_transport || !try_module_get(new_transport->module))
495-
return -ENODEV;
501+
if (!new_transport || !try_module_get(new_transport->module)) {
502+
ret = -ENODEV;
503+
goto err;
504+
}
505+
506+
/* It's safe to release the mutex after a successful try_module_get().
507+
* Whichever transport `new_transport` points at, it won't go away until
508+
* the last module_put() below or in vsock_deassign_transport().
509+
*/
510+
mutex_unlock(&vsock_register_mutex);
496511

497512
if (sk->sk_type == SOCK_SEQPACKET) {
498513
if (!new_transport->seqpacket_allow ||
@@ -511,6 +526,9 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
511526
vsk->transport = new_transport;
512527

513528
return 0;
529+
err:
530+
mutex_unlock(&vsock_register_mutex);
531+
return ret;
514532
}
515533
EXPORT_SYMBOL_GPL(vsock_assign_transport);
516534

0 commit comments

Comments
 (0)