Fix out-of-bounds write vulnerability caused by double-application of
mmap_offset in vhost_user_set_log_base(). The offset was used both as
a file offset in mmap() and then added again to compute log_base,
causing log_base to point beyond the mapped memory region.

Map the full region (size + offset) at file offset 0, matching the
correct pattern used in vhost_user_mmap_region(). Update munmap calls
to use the actual mapped size.

Fixes: bdd96d8ac76c ("vhost: fix offset while mapping log base address")

Bugzilla ID: 2004
CVE-2026-86563

Cc: [email protected]

Reported-by: Ivar Al-Safawi <[email protected]>
Acked-by: Kevin Traynor <[email protected]>
Signed-off-by: Maxime Coquelin <[email protected]>
---
 lib/vhost/vhost_user.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/lib/vhost/vhost_user.c b/lib/vhost/vhost_user.c
index ce3420ae90..018adfe4b2 100644
--- a/lib/vhost/vhost_user.c
+++ b/lib/vhost/vhost_user.c
@@ -296,7 +296,8 @@ vhost_backend_cleanup(struct virtio_net *dev)
        dev->guest_pages = NULL;
 
        if (dev->log_addr) {
-               munmap((void *)(uintptr_t)dev->log_addr, dev->log_size);
+               munmap((void *)(uintptr_t)dev->log_addr,
+                      dev->log_size + dev->log_base - dev->log_addr);
                dev->log_addr = 0;
        }
 
@@ -2726,7 +2727,7 @@ vhost_user_set_log_base(struct virtio_net **pdev,
         * mmap from 0 to workaround a hugepage mmap bug: mmap will
         * fail when offset is not page size aligned.
         */
-       addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, off);
+       addr = mmap(0, size + off, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        alignment = get_blk_size(fd);
        close(fd);
        if (addr == MAP_FAILED) {
@@ -2739,7 +2740,8 @@ vhost_user_set_log_base(struct virtio_net **pdev,
         * multiple VHOST_USER_SET_LOG_BASE.
         */
        if (dev->log_addr) {
-               munmap((void *)(uintptr_t)dev->log_addr, dev->log_size);
+               munmap((void *)(uintptr_t)dev->log_addr,
+                      dev->log_size + dev->log_base - dev->log_addr);
        }
        dev->log_addr = (uint64_t)(uintptr_t)addr;
        dev->log_base = dev->log_addr + off;
-- 
2.56.0

Reply via email to