aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorYuval Shaia <yuval.shaia.ml@gmail.com>2023-03-01 16:29:26 +0200
committerThomas Huth <thuth@redhat.com>2023-10-12 14:11:44 +0200
commit85fc35afa93c7320d1641d344d0c5dfbe341d087 (patch)
treea336fc87c991a6139c9b2c6a6f5ea14dce258ef7 /hw
parenta51e5124a655b3dad80b36b18547cb1eca2c5eb2 (diff)
downloadqemu-85fc35afa93c7320d1641d344d0c5dfbe341d087.zip
qemu-85fc35afa93c7320d1641d344d0c5dfbe341d087.tar.gz
qemu-85fc35afa93c7320d1641d344d0c5dfbe341d087.tar.bz2
hw/pvrdma: Protect against buggy or malicious guest driver
Guest driver allocates and initialize page tables to be used as a ring of descriptors for CQ and async events. The page table that represents the ring, along with the number of pages in the page table is passed to the device. Currently our device supports only one page table for a ring. Let's make sure that the number of page table entries the driver reports, do not exceeds the one page table size. Reported-by: Soul Chen <soulchen8650@gmail.com> Signed-off-by: Yuval Shaia <yuval.shaia.ml@gmail.com> Fixes: CVE-2023-1544 Message-ID: <20230301142926.18686-1-yuval.shaia.ml@gmail.com> Signed-off-by: Thomas Huth <thuth@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/rdma/vmw/pvrdma_main.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/hw/rdma/vmw/pvrdma_main.c b/hw/rdma/vmw/pvrdma_main.c
index 4fc6712..55b3380 100644
--- a/hw/rdma/vmw/pvrdma_main.c
+++ b/hw/rdma/vmw/pvrdma_main.c
@@ -91,19 +91,33 @@ static int init_dev_ring(PvrdmaRing *ring, PvrdmaRingState **ring_state,
dma_addr_t dir_addr, uint32_t num_pages)
{
uint64_t *dir, *tbl;
- int rc = 0;
+ int max_pages, rc = 0;
if (!num_pages) {
rdma_error_report("Ring pages count must be strictly positive");
return -EINVAL;
}
+ /*
+ * Make sure we can satisfy the requested number of pages in a single
+ * TARGET_PAGE_SIZE sized page table (taking into account that first entry
+ * is reserved for ring-state)
+ */
+ max_pages = TARGET_PAGE_SIZE / sizeof(dma_addr_t) - 1;
+ if (num_pages > max_pages) {
+ rdma_error_report("Maximum pages on a single directory must not exceed %d\n",
+ max_pages);
+ return -EINVAL;
+ }
+
dir = rdma_pci_dma_map(pci_dev, dir_addr, TARGET_PAGE_SIZE);
if (!dir) {
rdma_error_report("Failed to map to page directory (ring %s)", name);
rc = -ENOMEM;
goto out;
}
+
+ /* We support only one page table for a ring */
tbl = rdma_pci_dma_map(pci_dev, dir[0], TARGET_PAGE_SIZE);
if (!tbl) {
rdma_error_report("Failed to map to page table (ring %s)", name);