--- /dev/null
+From dd54bcf86c91a4455b1f95cbc8e9ac91205f3193 Mon Sep 17 00:00:00 2001
+From: Nikolay Kuratov <kniv@yandex-team.ru>
+Date: Tue, 5 Aug 2025 16:09:17 +0300
+Subject: vhost/net: Protect ubufs with rcu read lock in vhost_net_ubuf_put()
+
+From: Nikolay Kuratov <kniv@yandex-team.ru>
+
+commit dd54bcf86c91a4455b1f95cbc8e9ac91205f3193 upstream.
+
+When operating on struct vhost_net_ubuf_ref, the following execution
+sequence is theoretically possible:
+CPU0 is finalizing DMA operation CPU1 is doing VHOST_NET_SET_BACKEND
+ // ubufs->refcount == 2
+vhost_net_ubuf_put() vhost_net_ubuf_put_wait_and_free(oldubufs)
+ vhost_net_ubuf_put_and_wait()
+ vhost_net_ubuf_put()
+ int r = atomic_sub_return(1, &ubufs->refcount);
+ // r = 1
+int r = atomic_sub_return(1, &ubufs->refcount);
+// r = 0
+ wait_event(ubufs->wait, !atomic_read(&ubufs->refcount));
+ // no wait occurs here because condition is already true
+ kfree(ubufs);
+if (unlikely(!r))
+ wake_up(&ubufs->wait); // use-after-free
+
+This leads to use-after-free on ubufs access. This happens because CPU1
+skips waiting for wake_up() when refcount is already zero.
+
+To prevent that use a read-side RCU critical section in vhost_net_ubuf_put(),
+as suggested by Hillf Danton. For this lock to take effect, free ubufs with
+kfree_rcu().
+
+Cc: stable@vger.kernel.org
+Fixes: 0ad8b480d6ee9 ("vhost: fix ref cnt checking deadlock")
+Reported-by: Andrey Ryabinin <arbn@yandex-team.com>
+Suggested-by: Hillf Danton <hdanton@sina.com>
+Signed-off-by: Nikolay Kuratov <kniv@yandex-team.ru>
+Message-Id: <20250805130917.727332-1-kniv@yandex-team.ru>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/vhost/net.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/vhost/net.c
++++ b/drivers/vhost/net.c
+@@ -96,6 +96,7 @@ struct vhost_net_ubuf_ref {
+ atomic_t refcount;
+ wait_queue_head_t wait;
+ struct vhost_virtqueue *vq;
++ struct rcu_head rcu;
+ };
+
+ #define VHOST_NET_BATCH 64
+@@ -247,9 +248,13 @@ vhost_net_ubuf_alloc(struct vhost_virtqu
+
+ static int vhost_net_ubuf_put(struct vhost_net_ubuf_ref *ubufs)
+ {
+- int r = atomic_sub_return(1, &ubufs->refcount);
++ int r;
++
++ rcu_read_lock();
++ r = atomic_sub_return(1, &ubufs->refcount);
+ if (unlikely(!r))
+ wake_up(&ubufs->wait);
++ rcu_read_unlock();
+ return r;
+ }
+
+@@ -262,7 +267,7 @@ static void vhost_net_ubuf_put_and_wait(
+ static void vhost_net_ubuf_put_wait_and_free(struct vhost_net_ubuf_ref *ubufs)
+ {
+ vhost_net_ubuf_put_and_wait(ubufs);
+- kfree(ubufs);
++ kfree_rcu(ubufs, rcu);
+ }
+
+ static void vhost_net_clear_ubuf_info(struct vhost_net *n)