From 4b5f1ad5566ada230aaa2ce861b28d1895f1ea68 Mon Sep 17 00:00:00 2001 From: Stefano Garzarella Date: Wed, 23 Mar 2022 18:36:23 +0100 Subject: [PATCH 1/3] vsock/virtio: initialize vdev->priv before using VQs When we fill VQs with empty buffers and kick the host, it may send an interrupt. `vdev->priv` must be initialized before this since it is used in the virtqueue callbacks. Fixes: 0deab087b16a ("vsock/virtio: use RCU to avoid use-after-free on the_virtio_vsock") Suggested-by: Michael S. Tsirkin Signed-off-by: Stefano Garzarella Acked-by: Michael S. Tsirkin Reviewed-by: Stefan Hajnoczi Signed-off-by: Jakub Kicinski --- net/vmw_vsock/virtio_transport.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c index 5afc194a58bbd..3e5513934c9f5 100644 --- a/net/vmw_vsock/virtio_transport.c +++ b/net/vmw_vsock/virtio_transport.c @@ -622,6 +622,8 @@ static int virtio_vsock_probe(struct virtio_device *vdev) INIT_WORK(&vsock->event_work, virtio_transport_event_work); INIT_WORK(&vsock->send_pkt_work, virtio_transport_send_pkt_work); + vdev->priv = vsock; + mutex_lock(&vsock->tx_lock); vsock->tx_run = true; mutex_unlock(&vsock->tx_lock); @@ -639,7 +641,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev) if (virtio_has_feature(vdev, VIRTIO_VSOCK_F_SEQPACKET)) vsock->seqpacket_allow = true; - vdev->priv = vsock; rcu_assign_pointer(the_virtio_vsock, vsock); mutex_unlock(&the_virtio_vsock_mutex); From c1011c0b3a9c8d2065f425407475cbcc812540b7 Mon Sep 17 00:00:00 2001 From: Stefano Garzarella Date: Wed, 23 Mar 2022 18:36:24 +0100 Subject: [PATCH 2/3] vsock/virtio: read the negotiated features before using VQs Complete the driver configuration, reading the negotiated features, before using the VQs in the virtio_vsock_probe(). Fixes: 53efbba12cc7 ("virtio/vsock: enable SEQPACKET for transport") Suggested-by: Michael S. Tsirkin Reviewed-by: Stefan Hajnoczi Signed-off-by: Stefano Garzarella Acked-by: Michael S. Tsirkin Signed-off-by: Jakub Kicinski --- net/vmw_vsock/virtio_transport.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c index 3e5513934c9f5..3954d3be90838 100644 --- a/net/vmw_vsock/virtio_transport.c +++ b/net/vmw_vsock/virtio_transport.c @@ -622,6 +622,9 @@ static int virtio_vsock_probe(struct virtio_device *vdev) INIT_WORK(&vsock->event_work, virtio_transport_event_work); INIT_WORK(&vsock->send_pkt_work, virtio_transport_send_pkt_work); + if (virtio_has_feature(vdev, VIRTIO_VSOCK_F_SEQPACKET)) + vsock->seqpacket_allow = true; + vdev->priv = vsock; mutex_lock(&vsock->tx_lock); @@ -638,9 +641,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev) vsock->event_run = true; mutex_unlock(&vsock->event_lock); - if (virtio_has_feature(vdev, VIRTIO_VSOCK_F_SEQPACKET)) - vsock->seqpacket_allow = true; - rcu_assign_pointer(the_virtio_vsock, vsock); mutex_unlock(&the_virtio_vsock_mutex); From 88704454ef8b00ea91537ae0d47d9348077e0e72 Mon Sep 17 00:00:00 2001 From: Stefano Garzarella Date: Wed, 23 Mar 2022 18:36:25 +0100 Subject: [PATCH 3/3] vsock/virtio: enable VQs early on probe virtio spec requires drivers to set DRIVER_OK before using VQs. This is set automatically after probe returns, but virtio-vsock driver uses VQs in the probe function to fill rx and event VQs with new buffers. Let's fix this, calling virtio_device_ready() before using VQs in the probe function. Fixes: 0ea9e1d3a9e3 ("VSOCK: Introduce virtio_transport.ko") Signed-off-by: Stefano Garzarella Acked-by: Michael S. Tsirkin Reviewed-by: Stefan Hajnoczi Signed-off-by: Jakub Kicinski --- net/vmw_vsock/virtio_transport.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c index 3954d3be90838..ba1c8cc0c4671 100644 --- a/net/vmw_vsock/virtio_transport.c +++ b/net/vmw_vsock/virtio_transport.c @@ -627,6 +627,8 @@ static int virtio_vsock_probe(struct virtio_device *vdev) vdev->priv = vsock; + virtio_device_ready(vdev); + mutex_lock(&vsock->tx_lock); vsock->tx_run = true; mutex_unlock(&vsock->tx_lock);