aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorKlaus Jensen <k.jensen@samsung.com>2021-07-13 19:24:04 +0200
committerKlaus Jensen <k.jensen@samsung.com>2021-07-26 21:09:39 +0200
commit5029de44b5352d466f1b6e7c0a9f19e1259d33b3 (patch)
tree2c73635dd867fb08aea16173cc05e139eea2b851 /hw
parenta316aa50e6c9f25c22a705000271d33620a40595 (diff)
downloadqemu-5029de44b5352d466f1b6e7c0a9f19e1259d33b3.zip
qemu-5029de44b5352d466f1b6e7c0a9f19e1259d33b3.tar.gz
qemu-5029de44b5352d466f1b6e7c0a9f19e1259d33b3.tar.bz2
hw/nvme: fix out-of-bounds reads
Peter noticed that mmio access may read into the NvmeParams member in the NvmeCtrl struct. Fix the bounds check. Reported-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Klaus Jensen <k.jensen@samsung.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/nvme/ctrl.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index 23ff71f..10c2363 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -5969,23 +5969,26 @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size)
/* should RAZ, fall through for now */
}
- if (addr < sizeof(n->bar)) {
- /*
- * When PMRWBM bit 1 is set then read from
- * from PMRSTS should ensure prior writes
- * made it to persistent media
- */
- if (addr == NVME_REG_PMRSTS &&
- (NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) {
- memory_region_msync(&n->pmr.dev->mr, 0, n->pmr.dev->size);
- }
- memcpy(&val, ptr + addr, size);
- } else {
+ if (addr > sizeof(n->bar) - size) {
NVME_GUEST_ERR(pci_nvme_ub_mmiord_invalid_ofs,
"MMIO read beyond last register,"
" offset=0x%"PRIx64", returning 0", addr);
+
+ return 0;
}
+ /*
+ * When PMRWBM bit 1 is set then read from
+ * from PMRSTS should ensure prior writes
+ * made it to persistent media
+ */
+ if (addr == NVME_REG_PMRSTS &&
+ (NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) {
+ memory_region_msync(&n->pmr.dev->mr, 0, n->pmr.dev->size);
+ }
+
+ memcpy(&val, ptr + addr, size);
+
return val;
}