* [PATCH v2 1/4] vhost/vsock: split out vhost_vsock_drop_backends helper
2026-06-22 17:58 [PATCH v2 0/4] vhost/vsock: add support for VHOST_RESET_OWNER and CPR migration Andrey Drobyshev
@ 2026-06-22 17:58 ` Andrey Drobyshev
2026-06-22 17:58 ` [PATCH v2 2/4] vhost/vsock: suppress EHOSTUNREACH fast-fail during CPR pause Andrey Drobyshev
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Andrey Drobyshev @ 2026-06-22 17:58 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, virtualization, netdev, sgarzare, mst, stefanha,
dongli.zhang, maciej.szmigiero, bchaney, mark.kanda, ptikhomirov,
den, andrey.drobyshev
From: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Split the actual backend dropping part from vhost_vsock_stop. We're
going to need it for the VHOST_RESET_OWNER implementation in the
following patch, when vsock->dev.mutex is already taken and owner is
checked.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
---
drivers/vhost/vsock.c | 26 +++++++++++++++++---------
1 file changed, 17 insertions(+), 9 deletions(-)
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index 9aaab6bb8061..b12221ce6faf 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -664,9 +664,24 @@ static int vhost_vsock_start(struct vhost_vsock *vsock)
return ret;
}
-static int vhost_vsock_stop(struct vhost_vsock *vsock, bool check_owner)
+static void vhost_vsock_drop_backends(struct vhost_vsock *vsock)
{
+ struct vhost_virtqueue *vq;
size_t i;
+
+ lockdep_assert_held(&vsock->dev.mutex);
+
+ for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) {
+ vq = &vsock->vqs[i];
+
+ mutex_lock(&vq->mutex);
+ vhost_vq_set_backend(vq, NULL);
+ mutex_unlock(&vq->mutex);
+ }
+}
+
+static int vhost_vsock_stop(struct vhost_vsock *vsock, bool check_owner)
+{
int ret = 0;
mutex_lock(&vsock->dev.mutex);
@@ -677,14 +692,7 @@ static int vhost_vsock_stop(struct vhost_vsock *vsock, bool check_owner)
goto err;
}
- for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) {
- struct vhost_virtqueue *vq = &vsock->vqs[i];
-
- mutex_lock(&vq->mutex);
- vhost_vq_set_backend(vq, NULL);
- mutex_unlock(&vq->mutex);
- }
-
+ vhost_vsock_drop_backends(vsock);
err:
mutex_unlock(&vsock->dev.mutex);
return ret;
--
2.47.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 2/4] vhost/vsock: suppress EHOSTUNREACH fast-fail during CPR pause
2026-06-22 17:58 [PATCH v2 0/4] vhost/vsock: add support for VHOST_RESET_OWNER and CPR migration Andrey Drobyshev
2026-06-22 17:58 ` [PATCH v2 1/4] vhost/vsock: split out vhost_vsock_drop_backends helper Andrey Drobyshev
@ 2026-06-22 17:58 ` Andrey Drobyshev
2026-06-23 17:58 ` sashiko-bot
2026-06-22 17:58 ` [PATCH v2 3/4] vhost/vsock: re-scan TX virtqueue on device start Andrey Drobyshev
2026-06-22 17:58 ` [PATCH v2 4/4] vhost/vsock: add VHOST_RESET_OWNER ioctl Andrey Drobyshev
3 siblings, 1 reply; 7+ messages in thread
From: Andrey Drobyshev @ 2026-06-22 17:58 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, virtualization, netdev, sgarzare, mst, stefanha,
dongli.zhang, maciej.szmigiero, bchaney, mark.kanda, ptikhomirov,
den, andrey.drobyshev
Earlier commit bb26ed5f3a8b ("vhost/vsock: Refuse the connection
immediately when guest isn't ready") added a fast-fail in
vhost_transport_send_pkt(). It rejects every host send with -EHOSTUNREACH
until the destination calls SET_RUNNING(1). The fast-fail condition checks
whether device's backends are dropped, and if they're, the guest is
considered to be not ready.
However, there might be other reasons for backends to be nulled. In
particular, when QEMU is performing CPR (checkpoint-restore) migration,
device ownership is being RESET and SET again, which leads to backends
drop and reattach. If we end up connecting during this window, an
AF_VSOCK client gets -EHOSTUNREACH, which is wrong.
Add a 'started' flag which is set once in vhost_vsock_start() and is
never cleared. The behaviour changes to:
* When device was never started -> flag is unset -> no listener can
exist yet -> fast-fail;
* Once the device starts -> flag is set -> we don't fast-fail ->
we queue and preserve during any later stop / CPR pause.
Important caveat: after the first start, a connect during any stopped
window is queued instead of fast-failed. That was the behaviour before
the patch bb26ed5f3a8b, and we're restoring it now. However we still
keep the behaviour originally intended by that commit (i.e. fast-fail if
there's no real listener yet) while fixing the CPR path.
Signed-off-by: Denis V. Lunev <den@openvz.org>
Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
---
drivers/vhost/vsock.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index b12221ce6faf..bec6bcfd885f 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -61,6 +61,7 @@ struct vhost_vsock {
u32 guest_cid;
bool seqpacket_allow;
+ bool started; /* set on first SET_RUNNING(1); never cleared */
};
static u32 vhost_transport_get_local_cid(void)
@@ -302,17 +303,12 @@ vhost_transport_send_pkt(struct sk_buff *skb, struct net *net)
return -ENODEV;
}
- /* Fast-fail if the guest hasn't enabled the RX vq yet. Queuing the packet
- * and making the caller wait is pointless: even if the guest manages to init
- * within the timeout, it'll immediately reply with RST, because there's no
- * listener on the port yet.
- *
- * vhost_vq_get_backend() without vq->mutex is acceptable here: locking
- * the mutex would be too expensive in this hot path, and we already have
- * all the outcomes covered: if the backend becomes NULL right after the check,
- * vhost_transport_do_send_pkt() will check it under the mutex anyway.
+ /* Fast-fail until the guest first enables the device (SET_RUNNING(1)).
+ * Before that there is no listener, so queuing is pointless. 'started'
+ * is never cleared, so once we're up we keep queuing across later
+ * stop / CPR-pause windows.
*/
- if (unlikely(!data_race(vhost_vq_get_backend(&vsock->vqs[VSOCK_VQ_RX])))) {
+ if (unlikely(!READ_ONCE(vsock->started))) {
rcu_read_unlock();
kfree_skb(skb);
return -EHOSTUNREACH;
@@ -640,6 +636,11 @@ static int vhost_vsock_start(struct vhost_vsock *vsock)
mutex_unlock(&vq->mutex);
}
+ /* Set 'started' flag on the first start; never cleared, so send_pkt
+ * keeps queuing (instead of fast-failing) on later stop / CPR pauses.
+ */
+ WRITE_ONCE(vsock->started, true);
+
/* Some packets may have been queued before the device was started,
* let's kick the send worker to send them.
*/
@@ -728,6 +729,7 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
vsock->guest_cid = 0; /* no CID assigned yet */
vsock->seqpacket_allow = false;
+ vsock->started = false;
atomic_set(&vsock->queued_replies, 0);
--
2.47.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v2 2/4] vhost/vsock: suppress EHOSTUNREACH fast-fail during CPR pause
2026-06-22 17:58 ` [PATCH v2 2/4] vhost/vsock: suppress EHOSTUNREACH fast-fail during CPR pause Andrey Drobyshev
@ 2026-06-23 17:58 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-06-23 17:58 UTC (permalink / raw)
To: Andrey Drobyshev; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [Medium] The `started` flag is never cleared on VM reboot, permanently disabling the originally intended fast-fail behavior for all subsequent boots.
Pre-existing issues:
- [High] The patch exposes an unbounded memory leak and Local DoS vulnerability by queueing host-initiated packets indefinitely when the guest is paused.
--
commit c58db98ab34af8efb673c49c85406f685bf9805b
Author: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
vhost/vsock: suppress EHOSTUNREACH fast-fail during CPR pause
This patch alters the fast-fail condition in vhost_transport_send_pkt() to
check a new 'started' flag rather than checking if the device backends are
dropped. This ensures that host-initiated packets are queued rather than
fast-failed when a guest is temporarily paused during checkpoint-restore.
> diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
> index b12221ce6faf2..bec6bcfd885fa 100644
> --- a/drivers/vhost/vsock.c
> +++ b/drivers/vhost/vsock.c
[ ... ]
> @@ -302,17 +303,12 @@ vhost_transport_send_pkt(struct sk_buff *skb, struct net *net)
> return -ENODEV;
> }
>
> - /* Fast-fail if the guest hasn't enabled the RX vq yet. Queuing the packet
> - * and making the caller wait is pointless: even if the guest manages to init
> - * within the timeout, it'll immediately reply with RST, because there's no
> - * listener on the port yet.
> - *
> - * vhost_vq_get_backend() without vq->mutex is acceptable here: locking
> - * the mutex would be too expensive in this hot path, and we already have
> - * all the outcomes covered: if the backend becomes NULL right after the check,
> - * vhost_transport_do_send_pkt() will check it under the mutex anyway.
> + /* Fast-fail until the guest first enables the device (SET_RUNNING(1)).
> + * Before that there is no listener, so queuing is pointless. 'started'
> + * is never cleared, so once we're up we keep queuing across later
> + * stop / CPR-pause windows.
> */
> - if (unlikely(!data_race(vhost_vq_get_backend(&vsock->vqs[VSOCK_VQ_RX])))) {
> + if (unlikely(!READ_ONCE(vsock->started))) {
[Severity: High]
This is a pre-existing issue, but does changing the fast-fail condition to
rely on a flag that is never cleared expose an unbounded memory leak when a
VM is paused?
If a guest is paused, the device backend is stopped, but the started flag
remains true. A local user could repeatedly open a vsock socket, call
connect() with O_NONBLOCK to the paused guest's CID, and immediately close
the socket.
The close system call invokes virtio_transport_release(), which drops the
file descriptor but does not call cancel_pkt() to purge the pending
VIRTIO_VSOCK_OP_REQUEST packet from the transport's queue:
net/vmw_vsock/virtio_transport_common.c:virtio_transport_release() {
...
if (remove_sock) {
sock_set_flag(sk, SOCK_DONE);
virtio_transport_remove_sock(vsk);
}
}
Since skb_set_owner_w() binds the queued SKB to the socket's sk_wmem_alloc,
the orphaned socket and the SKB are kept alive in kernel memory. Because
send_pkt_queue is unbounded and there is no orphan socket limit, could this
allow a user to indefinitely leak kernel memory and exhaust host resources?
> rcu_read_unlock();
> kfree_skb(skb);
> return -EHOSTUNREACH;
[ ... ]
> @@ -640,6 +636,11 @@ static int vhost_vsock_start(struct vhost_vsock *vsock)
> mutex_unlock(&vq->mutex);
> }
>
> + /* Set 'started' flag on the first start; never cleared, so send_pkt
> + * keeps queuing (instead of fast-failing) on later stop / CPR pauses.
> + */
> + WRITE_ONCE(vsock->started, true);
> +
[Severity: Medium]
Does leaving this flag permanently set disable the originally intended
fast-fail behavior for all subsequent VM boots?
During a VM reboot, QEMU resets the vhost device via the VHOST_RESET_OWNER
ioctl, which clears the backends via vhost_vsock_drop_backends(), but
typically keeps the /dev/vhost-vsock file descriptor open.
Since the started flag is never reset to false during VHOST_RESET_OWNER,
host connection attempts during the rebooted VM's early boot phase will
bypass the fast-fail check and be queued indefinitely until the VM fully
boots.
Could this contradict the commit message's goal to keep the behavior
originally intended, which is to fast-fail if there is no listener yet?
> /* Some packets may have been queued before the device was started,
> * let's kick the send worker to send them.
> */
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260622175808.508084-1-andrey.drobyshev@virtuozzo.com?part=2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 3/4] vhost/vsock: re-scan TX virtqueue on device start
2026-06-22 17:58 [PATCH v2 0/4] vhost/vsock: add support for VHOST_RESET_OWNER and CPR migration Andrey Drobyshev
2026-06-22 17:58 ` [PATCH v2 1/4] vhost/vsock: split out vhost_vsock_drop_backends helper Andrey Drobyshev
2026-06-22 17:58 ` [PATCH v2 2/4] vhost/vsock: suppress EHOSTUNREACH fast-fail during CPR pause Andrey Drobyshev
@ 2026-06-22 17:58 ` Andrey Drobyshev
2026-06-22 17:58 ` [PATCH v2 4/4] vhost/vsock: add VHOST_RESET_OWNER ioctl Andrey Drobyshev
3 siblings, 0 replies; 7+ messages in thread
From: Andrey Drobyshev @ 2026-06-22 17:58 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, virtualization, netdev, sgarzare, mst, stefanha,
dongli.zhang, maciej.szmigiero, bchaney, mark.kanda, ptikhomirov,
den, andrey.drobyshev
During QEMU CPR live-update (and VHOST_RESET_OWNER in general) the guest
keeps running while the host drops and later re-attaches vhost backends.
If the guest adds a buffer to the TX virtqueue (guest->host) and kicks
while the backend is temporarily NULL (between vhost_vsock_drop_backends()
and the next vhost_vsock_start()), then the kick is delivered to the
vhost worker, handle_tx_kick() sees a NULL backend and returns, and the
kick signal is consumed. The buffer is then left in the ring.
Then upon device start vhost_vsock_start() only re-kicks the RX send
worker, never the TX VQ, so the buffer is processed only if the guest
happens to kick again. But if the guest itself is now waiting for data
from the host, it will never kick TX VQ again, and we end up in a
deadlock.
The issue itself is pre-existing, but it only manifests during a brief
pause caused by VHOST_RESET_OWNER. Namely, the deadlock is reproduced
during active host->guest socat data transfer under multiple consecutive
CPR live-update's.
To fix this, in vhost_vsock_start(), after kicking the RX send worker, also
queue the TX vq poll so any buffers the guest enqueued while we were paused
get scanned.
Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
---
drivers/vhost/vsock.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index bec6bcfd885f..81d4f7209719 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -646,6 +646,13 @@ static int vhost_vsock_start(struct vhost_vsock *vsock)
*/
vhost_vq_work_queue(&vsock->vqs[VSOCK_VQ_RX], &vsock->send_pkt_work);
+ /*
+ * Some packets might've also been queued in TX VQ. That is the case
+ * during the brief device pause caused by VHOST_RESET_OWNER. Re-scan
+ * the TX VQ here, mirroring the RX send-worker kick above.
+ */
+ vhost_poll_queue(&vsock->vqs[VSOCK_VQ_TX].poll);
+
mutex_unlock(&vsock->dev.mutex);
return 0;
--
2.47.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 4/4] vhost/vsock: add VHOST_RESET_OWNER ioctl
2026-06-22 17:58 [PATCH v2 0/4] vhost/vsock: add support for VHOST_RESET_OWNER and CPR migration Andrey Drobyshev
` (2 preceding siblings ...)
2026-06-22 17:58 ` [PATCH v2 3/4] vhost/vsock: re-scan TX virtqueue on device start Andrey Drobyshev
@ 2026-06-22 17:58 ` Andrey Drobyshev
2026-06-23 17:58 ` sashiko-bot
3 siblings, 1 reply; 7+ messages in thread
From: Andrey Drobyshev @ 2026-06-22 17:58 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, virtualization, netdev, sgarzare, mst, stefanha,
dongli.zhang, maciej.szmigiero, bchaney, mark.kanda, ptikhomirov,
den, andrey.drobyshev
From: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This ioctl is needed for QEMU's CPR (checkpoint-restore) migration of
the guest with vhost-vsock device. For this to work, we need to reset
the device ownership on the source side by calling RESET_OWNER, and then
claim it on the dest side by calling SET_OWNER. We expect not to lose any
AF_VSOCK connection while this happens.
RESET_OWNER keeps the guest CID hashed, so that connections survive. That
leaves the device reachable by the lockless send path while the worker is
being torn down: a concurrent vhost_transport_send_pkt() can call
vhost_vq_work_queue() as vhost_workers_free() frees the worker. That might
cause a use-after-free of vq->worker. In addition, any work queued onto
the dying worker leaves VHOST_WORK_QUEUED stuck, stalling send_pkt_queue
after resume.
Fence the send path around the teardown: send_pkt() only kicks the worker
while the backend is alive (otherwise the skb stays queued and
vhost_vsock_start() drains it on resume). And reset_owner() calls
synchronize_rcu() after drop_backends() so in-flight senders finish before
the worker is freed.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
---
drivers/vhost/vsock.c | 41 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index 81d4f7209719..7d0146cd38d2 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -318,7 +318,14 @@ vhost_transport_send_pkt(struct sk_buff *skb, struct net *net)
atomic_inc(&vsock->queued_replies);
virtio_vsock_skb_queue_tail(&vsock->send_pkt_queue, skb);
- vhost_vq_work_queue(&vsock->vqs[VSOCK_VQ_RX], &vsock->send_pkt_work);
+
+ /* Skip the kick once the backend is gone (stop/RESET_OWNER); the skb
+ * stays queued and vhost_vsock_start() drains it. Pairs with the
+ * synchronize_rcu() in vhost_vsock_reset_owner().
+ */
+ if (data_race(vhost_vq_get_backend(&vsock->vqs[VSOCK_VQ_RX])))
+ vhost_vq_work_queue(&vsock->vqs[VSOCK_VQ_RX],
+ &vsock->send_pkt_work);
rcu_read_unlock();
return len;
@@ -903,6 +910,36 @@ static int vhost_vsock_set_features(struct vhost_vsock *vsock, u64 features)
return -EFAULT;
}
+static int vhost_vsock_reset_owner(struct vhost_vsock *vsock)
+{
+ struct vhost_iotlb *umem;
+ long err;
+
+ mutex_lock(&vsock->dev.mutex);
+ err = vhost_dev_check_owner(&vsock->dev);
+ if (err)
+ goto done;
+ umem = vhost_dev_reset_owner_prepare();
+ if (!umem) {
+ err = -ENOMEM;
+ goto done;
+ }
+ vhost_vsock_drop_backends(vsock);
+
+ /* Let in-flight send_pkt() callers stop touching the worker before the
+ * flush + free below. Pairs with the backend check in
+ * vhost_transport_send_pkt().
+ */
+ synchronize_rcu();
+
+ vhost_vsock_flush(vsock);
+ vhost_dev_stop(&vsock->dev);
+ vhost_dev_reset_owner(&vsock->dev, umem);
+done:
+ mutex_unlock(&vsock->dev.mutex);
+ return err;
+}
+
static long vhost_vsock_dev_ioctl(struct file *f, unsigned int ioctl,
unsigned long arg)
{
@@ -946,6 +983,8 @@ static long vhost_vsock_dev_ioctl(struct file *f, unsigned int ioctl,
return -EOPNOTSUPP;
vhost_set_backend_features(&vsock->dev, features);
return 0;
+ case VHOST_RESET_OWNER:
+ return vhost_vsock_reset_owner(vsock);
default:
mutex_lock(&vsock->dev.mutex);
r = vhost_dev_ioctl(&vsock->dev, ioctl, argp);
--
2.47.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v2 4/4] vhost/vsock: add VHOST_RESET_OWNER ioctl
2026-06-22 17:58 ` [PATCH v2 4/4] vhost/vsock: add VHOST_RESET_OWNER ioctl Andrey Drobyshev
@ 2026-06-23 17:58 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-06-23 17:58 UTC (permalink / raw)
To: Andrey Drobyshev; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Missing backend check in `vhost_transport_cancel_pkt()` leads to a Use-After-Free of `vq->worker` and/or a permanently stuck `VHOST_WORK_QUEUED` flag during `VHOST_RESET_OWNER`.
--
commit 1246364b7bca9df01b3f2315a384db215bb18763
Author: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
vhost/vsock: add VHOST_RESET_OWNER ioctl
This patch adds the VHOST_RESET_OWNER ioctl for QEMU CPR migration of a
guest with a vhost-vsock device. It fences the send path around the teardown
by adding a backend check in vhost_transport_send_pkt() to prevent using
the worker after it is freed.
> diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
> index 81d4f72097191..7d0146cd38d26 100644
> --- a/drivers/vhost/vsock.c
> +++ b/drivers/vhost/vsock.c
[ ... ]
> @@ -903,6 +910,36 @@ static int vhost_vsock_set_features(struct vhost_vsock *vsock, u64 features)
> return -EFAULT;
> }
>
> +static int vhost_vsock_reset_owner(struct vhost_vsock *vsock)
> +{
> + struct vhost_iotlb *umem;
> + long err;
> +
> + mutex_lock(&vsock->dev.mutex);
> + err = vhost_dev_check_owner(&vsock->dev);
> + if (err)
> + goto done;
> + umem = vhost_dev_reset_owner_prepare();
> + if (!umem) {
> + err = -ENOMEM;
> + goto done;
> + }
> + vhost_vsock_drop_backends(vsock);
> +
> + /* Let in-flight send_pkt() callers stop touching the worker before the
> + * flush + free below. Pairs with the backend check in
> + * vhost_transport_send_pkt().
> + */
> + synchronize_rcu();
[Severity: High]
Does vhost_transport_cancel_pkt() also need a backend check similar to the
one added in vhost_transport_send_pkt()?
Since VHOST_RESET_OWNER leaves the vsock hashed so connections survive,
a concurrent socket close can still look up the vsock and call
vhost_transport_cancel_pkt().
If this happens after the synchronize_rcu() call finishes,
vhost_transport_cancel_pkt() can conditionally call
vhost_poll_queue(&tx_vq->poll). This unconditionally queues work without
checking if the backend is alive, which dereferences vq->worker.
Because vhost_workers_free() frees the worker synchronously via kfree()
during teardown, could this lead to a use-after-free of the worker
or a permanently stuck VHOST_WORK_QUEUED flag?
> +
> + vhost_vsock_flush(vsock);
> + vhost_dev_stop(&vsock->dev);
> + vhost_dev_reset_owner(&vsock->dev, umem);
> +done:
> + mutex_unlock(&vsock->dev.mutex);
> + return err;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260622175808.508084-1-andrey.drobyshev@virtuozzo.com?part=4
^ permalink raw reply [flat|nested] 7+ messages in thread