diff options
author | Klaus Jensen <k.jensen@samsung.com> | 2021-07-13 19:24:04 +0200 |
---|---|---|
committer | Klaus Jensen <k.jensen@samsung.com> | 2021-07-26 21:09:39 +0200 |
commit | 5029de44b5352d466f1b6e7c0a9f19e1259d33b3 (patch) | |
tree | 2c73635dd867fb08aea16173cc05e139eea2b851 /hw | |
parent | a316aa50e6c9f25c22a705000271d33620a40595 (diff) | |
download | qemu-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.c | 27 |
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; } |