Message ID | 20200530013828.59668-1-justin.he@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v3] virtio_vsock: Fix race condition in virtio_transport_recv_pkt | expand |
From: Jia He <justin.he@arm.com> Date: Sat, 30 May 2020 09:38:28 +0800 > When client on the host tries to connect(SOCK_STREAM, O_NONBLOCK) to the > server on the guest, there will be a panic on a ThunderX2 (armv8a server): ... > The race condition is as follows: > Task1 Task2 > ===== ===== > __sock_release virtio_transport_recv_pkt > __vsock_release vsock_find_bound_socket (found sk) > lock_sock_nested > vsock_remove_sock > sock_orphan > sk_set_socket(sk, NULL) > sk->sk_shutdown = SHUTDOWN_MASK > ... > release_sock > lock_sock > virtio_transport_recv_connecting > sk->sk_socket->state (panic!) > > The root cause is that vsock_find_bound_socket can't hold the lock_sock, > so there is a small race window between vsock_find_bound_socket() and > lock_sock(). If __vsock_release() is running in another task, > sk->sk_socket will be set to NULL inadvertently. > > This fixes it by checking sk->sk_shutdown(suggested by Stefano) after > lock_sock since sk->sk_shutdown is set to SHUTDOWN_MASK under the > protection of lock_sock_nested. > > Signed-off-by: Jia He <justin.he@arm.com> > Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> Applied and queued up for -stable, thank you.
diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 69efc891885f..0edda1edf988 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -1132,6 +1132,14 @@ void virtio_transport_recv_pkt(struct virtio_transport *t, lock_sock(sk); + /* Check if sk has been released before lock_sock */ + if (sk->sk_shutdown == SHUTDOWN_MASK) { + (void)virtio_transport_reset_no_sock(t, pkt); + release_sock(sk); + sock_put(sk); + goto free_pkt; + } + /* Update CID in case it has changed after a transport reset event */ vsk->local_addr.svm_cid = dst.svm_cid;