From: Greg Kroah-Hartman Date: Fri, 29 Aug 2025 14:23:29 +0000 (+0200) Subject: 6.12-stable patches X-Git-Tag: v5.4.298~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=422590fb31f8c5a45fec2092af552db3f5c3b4a6;p=thirdparty%2Fkernel%2Fstable-queue.git 6.12-stable patches added patches: vhost-net-protect-ubufs-with-rcu-read-lock-in-vhost_net_ubuf_put.patch --- diff --git a/queue-6.12/series b/queue-6.12/series index 62e35ec172..e260a49596 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -15,3 +15,4 @@ smb-client-fix-race-with-concurrent-opens-in-rename-.patch asoc-codecs-tx-macro-correct-tx_macro_component_drv-.patch erofs-fix-atomic-context-detection-when-config_debug.patch acpi-ec-add-device-to-acpi_ec_no_wakeup-qurik-list.patch +vhost-net-protect-ubufs-with-rcu-read-lock-in-vhost_net_ubuf_put.patch diff --git a/queue-6.12/vhost-net-protect-ubufs-with-rcu-read-lock-in-vhost_net_ubuf_put.patch b/queue-6.12/vhost-net-protect-ubufs-with-rcu-read-lock-in-vhost_net_ubuf_put.patch new file mode 100644 index 0000000000..9d745a3b7f --- /dev/null +++ b/queue-6.12/vhost-net-protect-ubufs-with-rcu-read-lock-in-vhost_net_ubuf_put.patch @@ -0,0 +1,79 @@ +From dd54bcf86c91a4455b1f95cbc8e9ac91205f3193 Mon Sep 17 00:00:00 2001 +From: Nikolay Kuratov +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 + +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 +Suggested-by: Hillf Danton +Signed-off-by: Nikolay Kuratov +Message-Id: <20250805130917.727332-1-kniv@yandex-team.ru> +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Greg Kroah-Hartman +--- + 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)