Commit 23a4edb6db for qemu.org

commit 23a4edb6dbe3dd5223326bdf03ae955321669b5c
Author: Daniil Tatianin <d-tatianin@yandex-team.ru>
Date:   Thu Nov 13 11:58:42 2025 +0300

    virtio/vhost: don't consider non-MAP_SHARED regions public

    Just having a file descriptor is not enough to consider a memory region
    public. If QEMU didn't map it as MAP_SHARED (in case of share=off), guest
    writes to this region won't be visible to the vhost-user backend, thus
    causing it to read all zeroes or garbage. Make sure we don't pass such
    regions and include that to our definition of what a private region is.

    Signed-off-by: Daniil Tatianin <d-tatianin@yandex-team.ru>
    Fixes: 552b25229c ("vhost: Rework memslot filtering and fix "used_memslot" tracking")
    Acked-by: Stefano Garzarella <sgarzare@redhat.com>
    Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
    Message-Id: <20251113085842.323745-1-d-tatianin@yandex-team.ru>

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 31e9704cdc..c6a5928cb1 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -592,11 +592,13 @@ static bool vhost_section(struct vhost_dev *dev, MemoryRegionSection *section)
         /*
          * Some backends (like vhost-user) can only handle memory regions
          * that have an fd (can be mapped into a different process). Filter
-         * the ones without an fd out, if requested.
-         *
-         * TODO: we might have to limit to MAP_SHARED as well.
+         * the ones without an fd out, if requested. Also make sure that
+         * this region is mapped as shared so that the vhost backend can
+         * observe modifications to this region, otherwise we consider it
+         * private.
          */
-        if (memory_region_get_fd(section->mr) < 0 &&
+        if ((memory_region_get_fd(section->mr) < 0 ||
+            !qemu_ram_is_shared(section->mr->ram_block)) &&
             dev->vhost_ops->vhost_backend_no_private_memslots &&
             dev->vhost_ops->vhost_backend_no_private_memslots(dev)) {
             trace_vhost_reject_section(mr->name, 2);