* Fri Jun 19 2026 Miroslav Rezanina <mrezanin@redhat.com> - 10.1.0-21
- kvm-hw-vfio-sort-and-validate-sparse-mmap-regions-by-off.patch [RHEL-150900] - kvm-vfio-Add-Error-parameter-to-vfio_region_setup.patch [RHEL-150900] - kvm-hw-vfio-align-mmap-to-power-of-2-of-region-size-for-.patch [RHEL-150900] - kvm-virtio-blk-add-missing-VIRTIO_BLK_T_SCSI_CMD-size-ch.patch [RHEL-184530] - Resolves: RHEL-150900 (NVIDIA:Grace:Backport hw/vfio: Enable hugepfnmap for non-power-of-2 device memory regions - RHEL 10.3) - Resolves: RHEL-184530 (CVE-2026-48914 qemu-kvm: Heap buffer overflow in virtio-blk SCSI request handling [rhel-10.3])
This commit is contained in:
parent
e2263aca2f
commit
704660b7d7
186
kvm-hw-vfio-align-mmap-to-power-of-2-of-region-size-for-.patch
Normal file
186
kvm-hw-vfio-align-mmap-to-power-of-2-of-region-size-for-.patch
Normal file
@ -0,0 +1,186 @@
|
||||
From 3107adc6f949c4e6b92d78c3311f2aad3e3bdc85 Mon Sep 17 00:00:00 2001
|
||||
From: Ankit Agrawal <ankita@nvidia.com>
|
||||
Date: Tue, 17 Feb 2026 15:30:10 +0000
|
||||
Subject: [PATCH 3/4] hw/vfio: align mmap to power-of-2 of region size for
|
||||
hugepfnmap
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
RH-Author: Cédric Le Goater <clg@redhat.com>
|
||||
RH-MergeRequest: 500: NVIDIA:Grace:Backport hw/vfio: Enable hugepfnmap for non-power-of-2 device memory regions - GB200
|
||||
RH-Jira: RHEL-150900
|
||||
RH-Acked-by: Rodolfo Vick <None>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [3/3] 34c31321e6c6613b7de013250a7f2927046b831d (clegoate/qemu-kvm-centos)
|
||||
|
||||
On Grace-based systems such as GB200, device memory is exposed as a
|
||||
BAR but the actual mappable size is not power-of-2 aligned. The
|
||||
previous algorithm aligned each sparse mmap area based on its
|
||||
individual size using ctz64() which prevented efficient huge page
|
||||
usage by the kernel.
|
||||
|
||||
Adjust VFIO region mapping alignment to use the next power-of-2 of
|
||||
the total region size and place the sparse subregions at their
|
||||
appropriate offset. This provides better opportunities to get huge
|
||||
alignment allowing the kernel to use larger page sizes for the VMA.
|
||||
|
||||
This enables the use of PMD-level huge pages which can significantly
|
||||
improve memory access performance and reduce TLB pressure for large
|
||||
device memory regions.
|
||||
|
||||
With this change:
|
||||
- Create a single aligned base mapping for the entire region
|
||||
- Change Alignment to be based on pow2ceil(region->size), capped at 1GiB
|
||||
- Unmap gaps between sparse regions
|
||||
- Use MAP_FIXED to overlay sparse mmap areas at their offsets
|
||||
|
||||
Example VMA for device memory of size 0x2F00F00000 on GB200:
|
||||
|
||||
Before (misaligned, no hugepfnmap):
|
||||
ff88ff000000-ffb7fff00000 rw-s 400000000000 00:06 727 /dev/vfio/devices/vfio1
|
||||
|
||||
After (aligned to 1GiB boundary, hugepfnmap enabled):
|
||||
ff8ac0000000-ffb9c0f00000 rw-s 400000000000 00:06 727 /dev/vfio/devices/vfio1
|
||||
|
||||
Requires sparse regions to be sorted by offset (done in previous
|
||||
patch) to correctly identify and handle gaps.
|
||||
|
||||
cc: Alex Williamson <alex@shazbot.org>
|
||||
Reviewed-by: Alex Williamson <alex@shazbot.org>
|
||||
Reviewed-by: Shameer Kolothum <skolothumtho@nvidia.com>
|
||||
Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
|
||||
Signed-off-by: Ankit Agrawal <ankita@nvidia.com>
|
||||
Reviewed-by: Cédric Le Goater <clg@redhat.com>
|
||||
Link: https://lore.kernel.org/qemu-devel/20260217153010.408739-4-ankita@nvidia.com
|
||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
||||
(cherry picked from commit 3863e47828d5bda1776fb7588a2187c7fba1d0c2)
|
||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
||||
---
|
||||
hw/vfio/region.c | 86 +++++++++++++++++++++++++++++++++---------------
|
||||
1 file changed, 59 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/hw/vfio/region.c b/hw/vfio/region.c
|
||||
index 055033a79e..1e9915fdd3 100644
|
||||
--- a/hw/vfio/region.c
|
||||
+++ b/hw/vfio/region.c
|
||||
@@ -344,8 +344,11 @@ static bool vfio_region_create_dma_buf(VFIORegion *region, Error **errp)
|
||||
|
||||
int vfio_region_mmap(VFIORegion *region)
|
||||
{
|
||||
- int i, ret, prot = 0;
|
||||
+ void *map_base, *map_align;
|
||||
Error *local_err = NULL;
|
||||
+ int i, ret, prot = 0;
|
||||
+ off_t map_offset = 0;
|
||||
+ size_t align;
|
||||
char *name;
|
||||
int fd;
|
||||
|
||||
@@ -356,41 +359,61 @@ int vfio_region_mmap(VFIORegion *region)
|
||||
prot |= region->flags & VFIO_REGION_INFO_FLAG_READ ? PROT_READ : 0;
|
||||
prot |= region->flags & VFIO_REGION_INFO_FLAG_WRITE ? PROT_WRITE : 0;
|
||||
|
||||
- for (i = 0; i < region->nr_mmaps; i++) {
|
||||
- size_t align = MIN(1ULL << ctz64(region->mmaps[i].size), 1 * GiB);
|
||||
- void *map_base, *map_align;
|
||||
+ /*
|
||||
+ * Align the mmap for more efficient mapping in the kernel. Ideally
|
||||
+ * we'd know the PMD and PUD mapping sizes to use as discrete alignment
|
||||
+ * intervals, but we don't. As of Linux v6.19, the largest PUD size
|
||||
+ * supporting huge pfnmap is 1GiB (ARCH_SUPPORTS_PUD_PFNMAP is only set
|
||||
+ * on x86_64).
|
||||
+ *
|
||||
+ * Align by power-of-two of the size of the entire region - capped
|
||||
+ * by 1G - and place the sparse subregions at their appropriate offset.
|
||||
+ * This will get maximum alignment.
|
||||
+ *
|
||||
+ * NB. qemu_memalign() and friends actually allocate memory, whereas
|
||||
+ * the region size here can exceed host memory, therefore we manually
|
||||
+ * create an oversized anonymous mapping and clean it up for alignment.
|
||||
+ */
|
||||
|
||||
- /*
|
||||
- * Align the mmap for more efficient mapping in the kernel. Ideally
|
||||
- * we'd know the PMD and PUD mapping sizes to use as discrete alignment
|
||||
- * intervals, but we don't. As of Linux v6.12, the largest PUD size
|
||||
- * supporting huge pfnmap is 1GiB (ARCH_SUPPORTS_PUD_PFNMAP is only set
|
||||
- * on x86_64). Align by power-of-two size, capped at 1GiB.
|
||||
- *
|
||||
- * NB. qemu_memalign() and friends actually allocate memory, whereas
|
||||
- * the region size here can exceed host memory, therefore we manually
|
||||
- * create an oversized anonymous mapping and clean it up for alignment.
|
||||
- */
|
||||
- map_base = mmap(0, region->mmaps[i].size + align, PROT_NONE,
|
||||
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
- if (map_base == MAP_FAILED) {
|
||||
- ret = -errno;
|
||||
- goto no_mmap;
|
||||
- }
|
||||
+ align = MIN(pow2ceil(region->size), 1 * GiB);
|
||||
|
||||
- fd = vfio_device_get_region_fd(region->vbasedev, region->nr);
|
||||
+ map_base = mmap(0, region->size + align, PROT_NONE,
|
||||
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
+ if (map_base == MAP_FAILED) {
|
||||
+ ret = -errno;
|
||||
+ trace_vfio_region_mmap_fault(memory_region_name(region->mem), -1,
|
||||
+ region->fd_offset,
|
||||
+ region->fd_offset + region->size - 1, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ fd = vfio_device_get_region_fd(region->vbasedev, region->nr);
|
||||
|
||||
- map_align = (void *)ROUND_UP((uintptr_t)map_base, (uintptr_t)align);
|
||||
- munmap(map_base, map_align - map_base);
|
||||
- munmap(map_align + region->mmaps[i].size,
|
||||
- align - (map_align - map_base));
|
||||
+ map_align = (void *)ROUND_UP((uintptr_t)map_base, (uintptr_t)align);
|
||||
+ munmap(map_base, map_align - map_base);
|
||||
+ munmap(map_align + region->size,
|
||||
+ align - (map_align - map_base));
|
||||
|
||||
- region->mmaps[i].mmap = mmap(map_align, region->mmaps[i].size, prot,
|
||||
+ /*
|
||||
+ * Regions should already be sorted by vfio_setup_region_sparse_mmaps().
|
||||
+ * This is critical for the following algorithm which relies on range
|
||||
+ * offsets being in ascending order.
|
||||
+ */
|
||||
+ for (i = 0; i < region->nr_mmaps; i++) {
|
||||
+ munmap(map_align + map_offset, region->mmaps[i].offset - map_offset);
|
||||
+ region->mmaps[i].mmap = mmap(map_align + region->mmaps[i].offset,
|
||||
+ region->mmaps[i].size, prot,
|
||||
MAP_SHARED | MAP_FIXED, fd,
|
||||
region->fd_offset +
|
||||
region->mmaps[i].offset);
|
||||
if (region->mmaps[i].mmap == MAP_FAILED) {
|
||||
ret = -errno;
|
||||
+ /*
|
||||
+ * Only unmap the rest of the region. Any mmaps that were successful
|
||||
+ * will be unmapped in no_mmap.
|
||||
+ */
|
||||
+ munmap(map_align + region->mmaps[i].offset,
|
||||
+ region->size - region->mmaps[i].offset);
|
||||
goto no_mmap;
|
||||
}
|
||||
|
||||
@@ -408,6 +431,15 @@ int vfio_region_mmap(VFIORegion *region)
|
||||
region->mmaps[i].offset,
|
||||
region->mmaps[i].offset +
|
||||
region->mmaps[i].size - 1);
|
||||
+
|
||||
+ map_offset = region->mmaps[i].offset + region->mmaps[i].size;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Unmap the rest of the region not covered by sparse mmap.
|
||||
+ */
|
||||
+ if (map_offset < region->size) {
|
||||
+ munmap(map_align + map_offset, region->size - map_offset);
|
||||
}
|
||||
|
||||
if (!vfio_region_create_dma_buf(region, &local_err)) {
|
||||
--
|
||||
2.52.0
|
||||
|
||||
121
kvm-hw-vfio-sort-and-validate-sparse-mmap-regions-by-off.patch
Normal file
121
kvm-hw-vfio-sort-and-validate-sparse-mmap-regions-by-off.patch
Normal file
@ -0,0 +1,121 @@
|
||||
From d0ac3ec4e1dc8ede0d4ea9bba020aa42845d2b0e Mon Sep 17 00:00:00 2001
|
||||
From: Ankit Agrawal <ankita@nvidia.com>
|
||||
Date: Tue, 17 Feb 2026 15:30:08 +0000
|
||||
Subject: [PATCH 1/4] hw/vfio: sort and validate sparse mmap regions by offset
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
RH-Author: Cédric Le Goater <clg@redhat.com>
|
||||
RH-MergeRequest: 500: NVIDIA:Grace:Backport hw/vfio: Enable hugepfnmap for non-power-of-2 device memory regions - GB200
|
||||
RH-Jira: RHEL-150900
|
||||
RH-Acked-by: Rodolfo Vick <None>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [1/3] d3a69bde63db8369e77d3703771fab637c9157a7 (clegoate/qemu-kvm-centos)
|
||||
|
||||
Sort sparse mmap regions by offset during region setup to ensure
|
||||
predictable mapping order, avoid overlaps and a proper handling
|
||||
of the gaps between sub-regions.
|
||||
|
||||
Add validation to detect overlapping sparse regions early during
|
||||
setup before any mapping operations begin.
|
||||
|
||||
The sorting is performed on the subregions ranges during
|
||||
vfio_setup_region_sparse_mmaps(). This also ensures that subsequent
|
||||
mapping code can rely on subregions being in ascending offset order.
|
||||
|
||||
This is preparatory work for alignment adjustments needed to support
|
||||
hugepfnmap on systems where device memory (e.g., Grace-based systems)
|
||||
may have non-power-of-2 sizes.
|
||||
|
||||
cc: Alex Williamson <alex@shazbot.org>
|
||||
Reviewed-by: Alex Williamson <alex@shazbot.org>
|
||||
Reviewed-by: Shameer Kolothum <skolothumtho@nvidia.com>
|
||||
Signed-off-by: Ankit Agrawal <ankita@nvidia.com>
|
||||
Reviewed-by: Cédric Le Goater <clg@redhat.com>
|
||||
Link: https://lore.kernel.org/qemu-devel/20260217153010.408739-2-ankita@nvidia.com
|
||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
||||
(cherry picked from commit da02b21cc70ef04a9ad15198f33551f17c94dff5)
|
||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
||||
---
|
||||
hw/vfio/region.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 45 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/vfio/region.c b/hw/vfio/region.c
|
||||
index 1deaef12fd..a61e47a79c 100644
|
||||
--- a/hw/vfio/region.c
|
||||
+++ b/hw/vfio/region.c
|
||||
@@ -149,6 +149,19 @@ static const MemoryRegionOps vfio_region_ops = {
|
||||
},
|
||||
};
|
||||
|
||||
+static int vfio_mmap_compare_offset(const void *a, const void *b)
|
||||
+{
|
||||
+ const VFIOMmap *mmap_a = a;
|
||||
+ const VFIOMmap *mmap_b = b;
|
||||
+
|
||||
+ if (mmap_a->offset < mmap_b->offset) {
|
||||
+ return -1;
|
||||
+ } else if (mmap_a->offset > mmap_b->offset) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int vfio_setup_region_sparse_mmaps(VFIORegion *region,
|
||||
struct vfio_region_info *info)
|
||||
{
|
||||
@@ -182,6 +195,35 @@ static int vfio_setup_region_sparse_mmaps(VFIORegion *region,
|
||||
region->nr_mmaps = j;
|
||||
region->mmaps = g_realloc(region->mmaps, j * sizeof(VFIOMmap));
|
||||
|
||||
+ /*
|
||||
+ * Sort sparse mmaps by offset to ensure proper handling of gaps
|
||||
+ * and predictable mapping order in vfio_region_mmap().
|
||||
+ */
|
||||
+ if (region->nr_mmaps > 1) {
|
||||
+ qsort(region->mmaps, region->nr_mmaps, sizeof(VFIOMmap),
|
||||
+ vfio_mmap_compare_offset);
|
||||
+
|
||||
+ /*
|
||||
+ * Validate that sparse regions don't overlap after sorting.
|
||||
+ */
|
||||
+ for (i = 1; i < region->nr_mmaps; i++) {
|
||||
+ off_t prev_end = region->mmaps[i - 1].offset +
|
||||
+ region->mmaps[i - 1].size;
|
||||
+ if (prev_end > region->mmaps[i].offset) {
|
||||
+ error_report("%s: overlapping sparse mmap regions detected "
|
||||
+ "in region %d: [0x%"PRIx64"-0x%"PRIx64"] overlaps "
|
||||
+ "with [0x%"PRIx64"-0x%"PRIx64"]",
|
||||
+ __func__, region->nr, region->mmaps[i - 1].offset,
|
||||
+ prev_end - 1, region->mmaps[i].offset,
|
||||
+ region->mmaps[i].offset + region->mmaps[i].size - 1);
|
||||
+ g_free(region->mmaps);
|
||||
+ region->mmaps = NULL;
|
||||
+ region->nr_mmaps = 0;
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -213,11 +255,13 @@ int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region,
|
||||
|
||||
ret = vfio_setup_region_sparse_mmaps(region, info);
|
||||
|
||||
- if (ret) {
|
||||
+ if (ret == -ENODEV) {
|
||||
region->nr_mmaps = 1;
|
||||
region->mmaps = g_new0(VFIOMmap, region->nr_mmaps);
|
||||
region->mmaps[0].offset = 0;
|
||||
region->mmaps[0].size = region->size;
|
||||
+ } else if (ret) {
|
||||
+ return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
2.52.0
|
||||
|
||||
147
kvm-vfio-Add-Error-parameter-to-vfio_region_setup.patch
Normal file
147
kvm-vfio-Add-Error-parameter-to-vfio_region_setup.patch
Normal file
@ -0,0 +1,147 @@
|
||||
From e4a9b1a603140f3e07aafed06d545125e856b608 Mon Sep 17 00:00:00 2001
|
||||
From: Ankit Agrawal <ankita@nvidia.com>
|
||||
Date: Tue, 17 Feb 2026 15:30:09 +0000
|
||||
Subject: [PATCH 2/4] vfio: Add Error ** parameter to vfio_region_setup()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
RH-Author: Cédric Le Goater <clg@redhat.com>
|
||||
RH-MergeRequest: 500: NVIDIA:Grace:Backport hw/vfio: Enable hugepfnmap for non-power-of-2 device memory regions - GB200
|
||||
RH-Jira: RHEL-150900
|
||||
RH-Acked-by: Rodolfo Vick <None>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [2/3] ae95924770d3a7828fc3d67df36fc6d09baf2e97 (clegoate/qemu-kvm-centos)
|
||||
|
||||
Add an Error **errp parameter to vfio_region_setup() and
|
||||
vfio_setup_region_sparse_mmaps to allow proper error handling
|
||||
instead of just returning error codes.
|
||||
|
||||
The function sets errors via error_setg() when failure occur.
|
||||
|
||||
Suggested-by: Cedric Le Goater <clg@redhat.com>
|
||||
Signed-off-by: Ankit Agrawal <ankita@nvidia.com>
|
||||
Reviewed-by: Cédric Le Goater <clg@redhat.com>
|
||||
Link: https://lore.kernel.org/qemu-devel/20260217153010.408739-3-ankita@nvidia.com
|
||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
||||
(cherry picked from commit c42010197eb905fe826550bb5f7c236d5534ddb4)
|
||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
||||
---
|
||||
hw/vfio/display.c | 6 +++---
|
||||
hw/vfio/pci.c | 3 +--
|
||||
hw/vfio/region.c | 20 +++++++++++---------
|
||||
hw/vfio/vfio-region.h | 2 +-
|
||||
4 files changed, 16 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/hw/vfio/display.c b/hw/vfio/display.c
|
||||
index faacd9019a..5a42a6f7a2 100644
|
||||
--- a/hw/vfio/display.c
|
||||
+++ b/hw/vfio/display.c
|
||||
@@ -446,13 +446,13 @@ static void vfio_display_region_update(void *opaque)
|
||||
|
||||
if (!dpy->region.buffer.size) {
|
||||
/* mmap region */
|
||||
+ Error *error = NULL;
|
||||
ret = vfio_region_setup(OBJECT(vdev), &vdev->vbasedev,
|
||||
&dpy->region.buffer,
|
||||
plane.region_index,
|
||||
- "display");
|
||||
+ "display", &error);
|
||||
if (ret != 0) {
|
||||
- error_report("%s: vfio_region_setup(%d): %s",
|
||||
- __func__, plane.region_index, strerror(-ret));
|
||||
+ error_report_err(error);
|
||||
goto err;
|
||||
}
|
||||
ret = vfio_region_mmap(&dpy->region.buffer);
|
||||
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
|
||||
index 378b475b2c..1ba66699dc 100644
|
||||
--- a/hw/vfio/pci.c
|
||||
+++ b/hw/vfio/pci.c
|
||||
@@ -2993,11 +2993,10 @@ bool vfio_pci_populate_device(VFIOPCIDevice *vdev, Error **errp)
|
||||
char *name = g_strdup_printf("%s BAR %d", vbasedev->name, i);
|
||||
|
||||
ret = vfio_region_setup(OBJECT(vdev), vbasedev,
|
||||
- &vdev->bars[i].region, i, name);
|
||||
+ &vdev->bars[i].region, i, name, errp);
|
||||
g_free(name);
|
||||
|
||||
if (ret) {
|
||||
- error_setg_errno(errp, -ret, "failed to get region %d info", i);
|
||||
return false;
|
||||
}
|
||||
|
||||
diff --git a/hw/vfio/region.c b/hw/vfio/region.c
|
||||
index a61e47a79c..055033a79e 100644
|
||||
--- a/hw/vfio/region.c
|
||||
+++ b/hw/vfio/region.c
|
||||
@@ -163,7 +163,8 @@ static int vfio_mmap_compare_offset(const void *a, const void *b)
|
||||
}
|
||||
|
||||
static int vfio_setup_region_sparse_mmaps(VFIORegion *region,
|
||||
- struct vfio_region_info *info)
|
||||
+ struct vfio_region_info *info,
|
||||
+ Error **errp)
|
||||
{
|
||||
struct vfio_info_cap_header *hdr;
|
||||
struct vfio_region_info_cap_sparse_mmap *sparse;
|
||||
@@ -210,12 +211,12 @@ static int vfio_setup_region_sparse_mmaps(VFIORegion *region,
|
||||
off_t prev_end = region->mmaps[i - 1].offset +
|
||||
region->mmaps[i - 1].size;
|
||||
if (prev_end > region->mmaps[i].offset) {
|
||||
- error_report("%s: overlapping sparse mmap regions detected "
|
||||
- "in region %d: [0x%"PRIx64"-0x%"PRIx64"] overlaps "
|
||||
- "with [0x%"PRIx64"-0x%"PRIx64"]",
|
||||
- __func__, region->nr, region->mmaps[i - 1].offset,
|
||||
- prev_end - 1, region->mmaps[i].offset,
|
||||
- region->mmaps[i].offset + region->mmaps[i].size - 1);
|
||||
+ error_setg(errp, "%s: overlapping sparse mmap regions detected "
|
||||
+ "in region %d: [0x%"PRIx64"-0x%"PRIx64"] overlaps "
|
||||
+ "with [0x%"PRIx64"-0x%"PRIx64"]",
|
||||
+ __func__, region->nr, region->mmaps[i - 1].offset,
|
||||
+ prev_end - 1, region->mmaps[i].offset,
|
||||
+ region->mmaps[i].offset + region->mmaps[i].size - 1);
|
||||
g_free(region->mmaps);
|
||||
region->mmaps = NULL;
|
||||
region->nr_mmaps = 0;
|
||||
@@ -228,13 +229,14 @@ static int vfio_setup_region_sparse_mmaps(VFIORegion *region,
|
||||
}
|
||||
|
||||
int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region,
|
||||
- int index, const char *name)
|
||||
+ int index, const char *name, Error **errp)
|
||||
{
|
||||
struct vfio_region_info *info = NULL;
|
||||
int ret;
|
||||
|
||||
ret = vfio_device_get_region_info(vbasedev, index, &info);
|
||||
if (ret) {
|
||||
+ error_setg_errno(errp, -ret, "failed to get region %d info", index);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -253,7 +255,7 @@ int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region,
|
||||
if (!vbasedev->no_mmap &&
|
||||
region->flags & VFIO_REGION_INFO_FLAG_MMAP) {
|
||||
|
||||
- ret = vfio_setup_region_sparse_mmaps(region, info);
|
||||
+ ret = vfio_setup_region_sparse_mmaps(region, info, errp);
|
||||
|
||||
if (ret == -ENODEV) {
|
||||
region->nr_mmaps = 1;
|
||||
diff --git a/hw/vfio/vfio-region.h b/hw/vfio/vfio-region.h
|
||||
index ede6e0c8f9..9b21d4ee5b 100644
|
||||
--- a/hw/vfio/vfio-region.h
|
||||
+++ b/hw/vfio/vfio-region.h
|
||||
@@ -38,7 +38,7 @@ void vfio_region_write(void *opaque, hwaddr addr,
|
||||
uint64_t vfio_region_read(void *opaque,
|
||||
hwaddr addr, unsigned size);
|
||||
int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region,
|
||||
- int index, const char *name);
|
||||
+ int index, const char *name, Error **errp);
|
||||
int vfio_region_mmap(VFIORegion *region);
|
||||
void vfio_region_mmaps_set_enabled(VFIORegion *region, bool enabled);
|
||||
void vfio_region_unmap(VFIORegion *region);
|
||||
--
|
||||
2.52.0
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
From 2bfe6c3fa58eea53c6b230069b10c3f8521fef68 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Date: Tue, 26 May 2026 11:49:57 -0400
|
||||
Subject: [PATCH 4/4] virtio-blk: add missing VIRTIO_BLK_T_SCSI_CMD size check
|
||||
(CVE-2026-48914)
|
||||
|
||||
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
RH-MergeRequest: 501: virtio-blk: add missing VIRTIO_BLK_T_SCSI_CMD size check (CVE-2026-48914)
|
||||
RH-Jira: RHEL-184530
|
||||
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [1/1] e2f65ed64020791c8b48c630b79d18371db30624 (stefanha/centos-stream-qemu-kvm)
|
||||
|
||||
Check that the iovec containing struct virtio_scsi_inhdr is large enough
|
||||
before storing an error value there.
|
||||
|
||||
Feifan Qian <bea1e@proton.me> pointed out that this can be used to
|
||||
corrupt heap memory when the descriptor uses an MMIO address and a
|
||||
length of 1, forcing QEMU to allocate a 1-byte heap bounce buffer.
|
||||
virtio_stl_p() stores 4 bytes and therefore corrupts whatever is beyond
|
||||
the bounce buffer.
|
||||
|
||||
Fixes: CVE-2026-48914
|
||||
Fixes: f34e73cd69bd ("virtio-blk: report non-zero status when failing SG_IO requests")
|
||||
Reported-by: Feifan Qian <bea1e@proton.me>
|
||||
Cc: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Message-ID: <20260526154957.1741622-1-stefanha@redhat.com>
|
||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit aeea0c2804c42f24915467a1e4c70e649e39b8e0)
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
---
|
||||
hw/block/virtio-blk.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
|
||||
index 9bab2716c1..a0678300b4 100644
|
||||
--- a/hw/block/virtio-blk.c
|
||||
+++ b/hw/block/virtio-blk.c
|
||||
@@ -200,10 +200,16 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
||||
|
||||
/*
|
||||
* The scsi inhdr is placed in the second-to-last input segment, just
|
||||
- * before the regular inhdr.
|
||||
+ * before the regular inhdr. VIRTIO implementations normally do not rely on
|
||||
+ * the precise message framing, but legacy implementations did and so we do
|
||||
+ * too for the legacy virtio-blk SCSI request type.
|
||||
*
|
||||
* Just put anything nonzero so that the ioctl fails in the guest.
|
||||
*/
|
||||
+ if (elem->in_sg[elem->in_num - 2].iov_len != sizeof(*scsi)) {
|
||||
+ status = VIRTIO_BLK_S_IOERR;
|
||||
+ goto fail;
|
||||
+ }
|
||||
scsi = (void *)elem->in_sg[elem->in_num - 2].iov_base;
|
||||
virtio_stl_p(vdev, &scsi->errors, 255);
|
||||
status = VIRTIO_BLK_S_UNSUPP;
|
||||
--
|
||||
2.52.0
|
||||
|
||||
@ -143,7 +143,7 @@ Obsoletes: %{name}-block-ssh <= %{epoch}:%{version} \
|
||||
Summary: QEMU is a machine emulator and virtualizer
|
||||
Name: qemu-kvm
|
||||
Version: 10.1.0
|
||||
Release: 20%{?rcrel}%{?dist}%{?cc_suffix}
|
||||
Release: 21%{?rcrel}%{?dist}%{?cc_suffix}
|
||||
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
|
||||
# Epoch 15 used for RHEL 8
|
||||
# Epoch 17 used for RHEL 9 (due to release versioning offset in RHEL 8.5)
|
||||
@ -694,6 +694,14 @@ Patch268: kvm-vfio-container-Restrict-dma_map_file-to-shared-RAM-o.patch
|
||||
Patch269: kvm-scsi-change-buf_size-to-unsigned-int-in-scsi_SG_IO.patch
|
||||
# For RHEL-153123 - live migration failed or get failed WSFC test result during WSFC testing [rhel-10.3]
|
||||
Patch270: kvm-scsi-handle-reservation-changes-across-migration.patch
|
||||
# For RHEL-150900 - NVIDIA:Grace:Backport hw/vfio: Enable hugepfnmap for non-power-of-2 device memory regions - RHEL 10.3
|
||||
Patch271: kvm-hw-vfio-sort-and-validate-sparse-mmap-regions-by-off.patch
|
||||
# For RHEL-150900 - NVIDIA:Grace:Backport hw/vfio: Enable hugepfnmap for non-power-of-2 device memory regions - RHEL 10.3
|
||||
Patch272: kvm-vfio-Add-Error-parameter-to-vfio_region_setup.patch
|
||||
# For RHEL-150900 - NVIDIA:Grace:Backport hw/vfio: Enable hugepfnmap for non-power-of-2 device memory regions - RHEL 10.3
|
||||
Patch273: kvm-hw-vfio-align-mmap-to-power-of-2-of-region-size-for-.patch
|
||||
# For RHEL-184530 - CVE-2026-48914 qemu-kvm: Heap buffer overflow in virtio-blk SCSI request handling [rhel-10.3]
|
||||
Patch274: kvm-virtio-blk-add-missing-VIRTIO_BLK_T_SCSI_CMD-size-ch.patch
|
||||
|
||||
%if %{have_clang}
|
||||
BuildRequires: clang
|
||||
@ -1773,6 +1781,16 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Fri Jun 19 2026 Miroslav Rezanina <mrezanin@redhat.com> - 10.1.0-21
|
||||
- kvm-hw-vfio-sort-and-validate-sparse-mmap-regions-by-off.patch [RHEL-150900]
|
||||
- kvm-vfio-Add-Error-parameter-to-vfio_region_setup.patch [RHEL-150900]
|
||||
- kvm-hw-vfio-align-mmap-to-power-of-2-of-region-size-for-.patch [RHEL-150900]
|
||||
- kvm-virtio-blk-add-missing-VIRTIO_BLK_T_SCSI_CMD-size-ch.patch [RHEL-184530]
|
||||
- Resolves: RHEL-150900
|
||||
(NVIDIA:Grace:Backport hw/vfio: Enable hugepfnmap for non-power-of-2 device memory regions - RHEL 10.3)
|
||||
- Resolves: RHEL-184530
|
||||
(CVE-2026-48914 qemu-kvm: Heap buffer overflow in virtio-blk SCSI request handling [rhel-10.3])
|
||||
|
||||
* Mon Jun 08 2026 Miroslav Rezanina <mrezanin@redhat.com> - 10.1.0-20
|
||||
- kvm-accel-mshv-Remove-remap-overlapping-mappings-code.patch [RHEL-178767]
|
||||
- kvm-accel-mshv-implement-cpu_thread_is_idle-hook.patch [RHEL-178767]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user