summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefano Garzarella <sgarzare@redhat.com>2026-04-17 15:26:44 +0200
committerMichael Tokarev <mjt@tls.msk.ru>2026-06-16 19:15:20 +0300
commit92d7bb038e011e76b631a6213807469c6b5edd51 (patch)
tree893266d80606852b89828760251e938c4c6c737d
parent36d13850196bb88fa936c4e562e6224cca4fe51b (diff)
downloadqemu-92d7bb038e011e76b631a6213807469c6b5edd51.tar.gz
qemu-92d7bb038e011e76b631a6213807469c6b5edd51.zip
libvhost-user: fix buffer overflow in virtqueue_read_indirect_desc()
virtqueue_read_indirect_desc() copies an indirect descriptor table into a buffer in chunks when the table crosses a memory region boundary. The destination is a struct vring_desc pointer but is advanced by a byte count, so each increment moves the pointer by read_len elements instead of read_len bytes, writing beyond the buffer. Use a char pointer for the destination so that the arithmetic advances correctly. While at it, change the source from a struct vring_desc pointer to a void pointer: when the table is split across regions, vu_gpa_to_va() can return a pointer into the middle of a descriptor, so casting it to a struct vring_desc pointer is wrong. The pointer is only used as a memcpy() source, so a void pointer is fine. Fixes: CVE-2026-6425 Fixes: 293084a719 ("libvhost-user: Support across-memory-boundary access") Cc: qemu-stable@nongnu.org Reported-by: DARKNAVY <vr@darknavy.com> Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-Id: <20260417132645.121192-2-sgarzare@redhat.com> (cherry picked from commit 85805ee887be4adddb1f1a34f526968adc95e582) Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
-rw-r--r--subprojects/libvhost-user/libvhost-user.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
index 9c630c2170..014d210748 100644
--- a/subprojects/libvhost-user/libvhost-user.c
+++ b/subprojects/libvhost-user/libvhost-user.c
@@ -2391,8 +2391,9 @@ static int
virtqueue_read_indirect_desc(VuDev *dev, struct vring_desc *desc,
uint64_t addr, size_t len)
{
- struct vring_desc *ori_desc;
+ char *dst_desc = (char *)desc;
uint64_t read_len;
+ void *ori_desc;
if (len > (VIRTQUEUE_MAX_SIZE * sizeof(struct vring_desc))) {
return -1;
@@ -2409,10 +2410,10 @@ virtqueue_read_indirect_desc(VuDev *dev, struct vring_desc *desc,
return -1;
}
- memcpy(desc, ori_desc, read_len);
+ memcpy(dst_desc, ori_desc, read_len);
len -= read_len;
addr += read_len;
- desc += read_len;
+ dst_desc += read_len;
}
return 0;