mirror of
https://git.yoctoproject.org/poky
synced 2026-06-03 13:49:49 +00:00
qemu: fix CVE-2021-3929 nvme DMA reentrancy issue leads to use-after-free
(From OE-Core rev: 18056190f72eef9a44397cd87d79022dd2a9d4e3) Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com> Signed-off-by: Steve Sakoman <steve@sakoman.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
committed by
Richard Purdie
parent
4853705635
commit
3c3039aac4
@@ -115,6 +115,7 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \
|
||||
file://CVE-2021-3638.patch \
|
||||
file://CVE-2021-20196.patch \
|
||||
file://CVE-2021-3507.patch \
|
||||
file://CVE-2021-3929.patch \
|
||||
"
|
||||
UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar"
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
From 736b01642d85be832385063f278fe7cd4ffb5221 Mon Sep 17 00:00:00 2001
|
||||
From: Klaus Jensen <k.jensen@samsung.com>
|
||||
Date: Fri, 17 Dec 2021 10:44:01 +0100
|
||||
Subject: [PATCH] hw/nvme: fix CVE-2021-3929
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This fixes CVE-2021-3929 "locally" by denying DMA to the iomem of the
|
||||
device itself. This still allows DMA to MMIO regions of other devices
|
||||
(e.g. doing P2P DMA to the controller memory buffer of another NVMe
|
||||
device).
|
||||
|
||||
Fixes: CVE-2021-3929
|
||||
Reported-by: Qiuhao Li <Qiuhao.Li@outlook.com>
|
||||
Reviewed-by: Keith Busch <kbusch@kernel.org>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
|
||||
|
||||
Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/736b01642d85be832385]
|
||||
CVE: CVE-2021-3929
|
||||
Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
|
||||
---
|
||||
hw/block/nvme.c | 23 +++++++++++++++++++++++
|
||||
hw/block/nvme.h | 1 +
|
||||
2 files changed, 24 insertions(+)
|
||||
|
||||
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
|
||||
index 12d82542..e7d0750c 100644
|
||||
--- a/hw/block/nvme.c
|
||||
+++ b/hw/block/nvme.c
|
||||
@@ -52,8 +52,31 @@
|
||||
|
||||
static void nvme_process_sq(void *opaque);
|
||||
|
||||
+static inline bool nvme_addr_is_iomem(NvmeCtrl *n, hwaddr addr)
|
||||
+{
|
||||
+ hwaddr hi, lo;
|
||||
+
|
||||
+ /*
|
||||
+ * The purpose of this check is to guard against invalid "local" access to
|
||||
+ * the iomem (i.e. controller registers). Thus, we check against the range
|
||||
+ * covered by the 'bar0' MemoryRegion since that is currently composed of
|
||||
+ * two subregions (the NVMe "MBAR" and the MSI-X table/pba). Note, however,
|
||||
+ * that if the device model is ever changed to allow the CMB to be located
|
||||
+ * in BAR0 as well, then this must be changed.
|
||||
+ */
|
||||
+ lo = n->bar0.addr;
|
||||
+ hi = lo + int128_get64(n->bar0.size);
|
||||
+
|
||||
+ return addr >= lo && addr < hi;
|
||||
+}
|
||||
+
|
||||
static void nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size)
|
||||
{
|
||||
+
|
||||
+ if (nvme_addr_is_iomem(n, addr)) {
|
||||
+ return NVME_DATA_TRAS_ERROR;
|
||||
+ }
|
||||
+
|
||||
if (n->cmbsz && addr >= n->ctrl_mem.addr &&
|
||||
addr < (n->ctrl_mem.addr + int128_get64(n->ctrl_mem.size))) {
|
||||
memcpy(buf, (void *)&n->cmbuf[addr - n->ctrl_mem.addr], size);
|
||||
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
|
||||
index 557194ee..5a2b119c 100644
|
||||
--- a/hw/block/nvme.h
|
||||
+++ b/hw/block/nvme.h
|
||||
@@ -59,6 +59,7 @@ typedef struct NvmeNamespace {
|
||||
|
||||
typedef struct NvmeCtrl {
|
||||
PCIDevice parent_obj;
|
||||
+ MemoryRegion bar0;
|
||||
MemoryRegion iomem;
|
||||
MemoryRegion ctrl_mem;
|
||||
NvmeBar bar;
|
||||
--
|
||||
2.30.2
|
||||
|
||||
Reference in New Issue
Block a user