mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-28 03:42:09 +00:00
The virtio vsock driver has a small window during initialization where it can silently drop replies to connection requests. Because no reply is sent, kata waits for 10 seconds and in the end it generates a connection timeout error in HybridVSockDialer. Fixes: #8291 Signed-off-by: Alexandru Matei <alexandru.matei@uipath.com>
152 lines
6.0 KiB
Diff
152 lines
6.0 KiB
Diff
From a44b98fc926521d6cf642ed945e1d0781973d0d8 Mon Sep 17 00:00:00 2001
|
|
From: Jiyong Park <jiyong@google.com>
|
|
Date: Fri, 11 Mar 2022 11:00:16 +0900
|
|
Subject: [PATCH 2/7] vsock: each transport cycles only on its own sockets
|
|
|
|
When iterating over sockets using vsock_for_each_connected_socket, make
|
|
sure that a transport filters out sockets that don't belong to the
|
|
transport.
|
|
|
|
There actually was an issue caused by this; in a nested VM
|
|
configuration, destroying the nested VM (which often involves the
|
|
closing of /dev/vhost-vsock if there was h2g connections to the nested
|
|
VM) kills not only the h2g connections, but also all existing g2h
|
|
connections to the (outmost) host which are totally unrelated.
|
|
|
|
Tested: Executed the following steps on Cuttlefish (Android running on a
|
|
VM) [1]: (1) Enter into an `adb shell` session - to have a g2h
|
|
connection inside the VM, (2) open and then close /dev/vhost-vsock by
|
|
`exec 3< /dev/vhost-vsock && exec 3<&-`, (3) observe that the adb
|
|
session is not reset.
|
|
|
|
[1] https://android.googlesource.com/device/google/cuttlefish/
|
|
|
|
Fixes: c0cfa2d8a788 ("vsock: add multi-transports support")
|
|
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
Acked-by: Michael S. Tsirkin <mst@redhat.com>
|
|
Signed-off-by: Jiyong Park <jiyong@google.com>
|
|
Link: https://lore.kernel.org/r/20220311020017.1509316-1-jiyong@google.com
|
|
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
---
|
|
drivers/vhost/vsock.c | 3 ++-
|
|
include/net/af_vsock.h | 3 ++-
|
|
net/vmw_vsock/af_vsock.c | 9 +++++++--
|
|
net/vmw_vsock/virtio_transport.c | 7 +++++--
|
|
net/vmw_vsock/vmci_transport.c | 5 ++++-
|
|
5 files changed, 20 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
|
|
index a483cec31d5c..e413aaaca8f9 100644
|
|
--- a/drivers/vhost/vsock.c
|
|
+++ b/drivers/vhost/vsock.c
|
|
@@ -695,7 +695,8 @@ static int vhost_vsock_dev_release(struct inode *inode, struct file *file)
|
|
|
|
/* Iterating over all connections for all CIDs to find orphans is
|
|
* inefficient. Room for improvement here. */
|
|
- vsock_for_each_connected_socket(vhost_vsock_reset_orphans);
|
|
+ vsock_for_each_connected_socket(&vhost_transport.transport,
|
|
+ vhost_vsock_reset_orphans);
|
|
|
|
vhost_vsock_stop(vsock);
|
|
vhost_vsock_flush(vsock);
|
|
diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
|
|
index b1c717286993..4d8589244dc7 100644
|
|
--- a/include/net/af_vsock.h
|
|
+++ b/include/net/af_vsock.h
|
|
@@ -197,7 +197,8 @@ struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr);
|
|
struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
|
|
struct sockaddr_vm *dst);
|
|
void vsock_remove_sock(struct vsock_sock *vsk);
|
|
-void vsock_for_each_connected_socket(void (*fn)(struct sock *sk));
|
|
+void vsock_for_each_connected_socket(struct vsock_transport *transport,
|
|
+ void (*fn)(struct sock *sk));
|
|
int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk);
|
|
bool vsock_find_cid(unsigned int cid);
|
|
|
|
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
|
|
index 791955f5e7ec..bc3b85838158 100644
|
|
--- a/net/vmw_vsock/af_vsock.c
|
|
+++ b/net/vmw_vsock/af_vsock.c
|
|
@@ -333,7 +333,8 @@ void vsock_remove_sock(struct vsock_sock *vsk)
|
|
}
|
|
EXPORT_SYMBOL_GPL(vsock_remove_sock);
|
|
|
|
-void vsock_for_each_connected_socket(void (*fn)(struct sock *sk))
|
|
+void vsock_for_each_connected_socket(struct vsock_transport *transport,
|
|
+ void (*fn)(struct sock *sk))
|
|
{
|
|
int i;
|
|
|
|
@@ -342,8 +343,12 @@ void vsock_for_each_connected_socket(void (*fn)(struct sock *sk))
|
|
for (i = 0; i < ARRAY_SIZE(vsock_connected_table); i++) {
|
|
struct vsock_sock *vsk;
|
|
list_for_each_entry(vsk, &vsock_connected_table[i],
|
|
- connected_table)
|
|
+ connected_table) {
|
|
+ if (vsk->transport != transport)
|
|
+ continue;
|
|
+
|
|
fn(sk_vsock(vsk));
|
|
+ }
|
|
}
|
|
|
|
spin_unlock_bh(&vsock_table_lock);
|
|
diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c
|
|
index 3a056f8affd1..e131121533ad 100644
|
|
--- a/net/vmw_vsock/virtio_transport.c
|
|
+++ b/net/vmw_vsock/virtio_transport.c
|
|
@@ -24,6 +24,7 @@
|
|
static struct workqueue_struct *virtio_vsock_workqueue;
|
|
static struct virtio_vsock __rcu *the_virtio_vsock;
|
|
static DEFINE_MUTEX(the_virtio_vsock_mutex); /* protects the_virtio_vsock */
|
|
+static struct virtio_transport virtio_transport; /* forward declaration */
|
|
|
|
struct virtio_vsock {
|
|
struct virtio_device *vdev;
|
|
@@ -383,7 +384,8 @@ static void virtio_vsock_event_handle(struct virtio_vsock *vsock,
|
|
switch (le32_to_cpu(event->id)) {
|
|
case VIRTIO_VSOCK_EVENT_TRANSPORT_RESET:
|
|
virtio_vsock_update_guest_cid(vsock);
|
|
- vsock_for_each_connected_socket(virtio_vsock_reset_sock);
|
|
+ vsock_for_each_connected_socket(&virtio_transport.transport,
|
|
+ virtio_vsock_reset_sock);
|
|
break;
|
|
}
|
|
}
|
|
@@ -635,7 +637,8 @@ static void virtio_vsock_remove(struct virtio_device *vdev)
|
|
synchronize_rcu();
|
|
|
|
/* Reset all connected sockets when the device disappear */
|
|
- vsock_for_each_connected_socket(virtio_vsock_reset_sock);
|
|
+ vsock_for_each_connected_socket(&virtio_transport.transport,
|
|
+ virtio_vsock_reset_sock);
|
|
|
|
/* Stop all work handlers to make sure no one is accessing the device,
|
|
* so we can safely call vdev->config->reset().
|
|
diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
|
|
index 8b65323207db..87de3477cb6d 100644
|
|
--- a/net/vmw_vsock/vmci_transport.c
|
|
+++ b/net/vmw_vsock/vmci_transport.c
|
|
@@ -75,6 +75,8 @@ static u32 vmci_transport_qp_resumed_sub_id = VMCI_INVALID_ID;
|
|
|
|
static int PROTOCOL_OVERRIDE = -1;
|
|
|
|
+static struct vsock_transport vmci_transport; /* forward declaration */
|
|
+
|
|
/* Helper function to convert from a VMCI error code to a VSock error code. */
|
|
|
|
static s32 vmci_transport_error_to_vsock_error(s32 vmci_error)
|
|
@@ -883,7 +885,8 @@ static void vmci_transport_qp_resumed_cb(u32 sub_id,
|
|
const struct vmci_event_data *e_data,
|
|
void *client_data)
|
|
{
|
|
- vsock_for_each_connected_socket(vmci_transport_handle_detach);
|
|
+ vsock_for_each_connected_socket(&vmci_transport,
|
|
+ vmci_transport_handle_detach);
|
|
}
|
|
|
|
static void vmci_transport_recv_pkt_work(struct work_struct *work)
|
|
--
|
|
2.34.1
|
|
|