a75c8ea61f
hcd-xhci: infinite loop in xhci_ring_chain_length (CVE-2020-14394) (rhbz#1908050) ati-vga: out-of-bounds write in ati_2d_blt (CVE-2021-3638) (rhbz#1979882) acpi erst: memory corruption issues (CVE-2022-4172) (rhbz#2149106) qxl: qxl_phys2virt unsafe address translation (CVE-2022-4144) (rhbz#2148542) Signed-off-by: Mauro Matteo Cascella <mcascell@redhat.com>
71 lines
2.5 KiB
Diff
71 lines
2.5 KiB
Diff
From: Thomas Huth <thuth@redhat.com>
|
|
Date: Thu, 4 Aug 2022 15:13:00 +0200
|
|
Subject: [PATCH] hw/usb/hcd-xhci: Fix unbounded loop in
|
|
xhci_ring_chain_length() (CVE-2020-14394)
|
|
|
|
The loop condition in xhci_ring_chain_length() is under control of
|
|
the guest, and additionally the code does not check for failed DMA
|
|
transfers (e.g. if reaching the end of the RAM), so the loop there
|
|
could run for a very long time or even forever. Fix it by checking
|
|
the return value of dma_memory_read() and by introducing a maximum
|
|
loop length.
|
|
|
|
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/646
|
|
Message-Id: <20220804131300.96368-1-thuth@redhat.com>
|
|
Reviewed-by: Mauro Matteo Cascella <mcascell@redhat.com>
|
|
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
|
---
|
|
hw/usb/hcd-xhci.c | 23 +++++++++++++++++++----
|
|
1 file changed, 19 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
|
|
index 0cd0a5e540..213d0be6b6 100644
|
|
--- a/hw/usb/hcd-xhci.c
|
|
+++ b/hw/usb/hcd-xhci.c
|
|
@@ -21,6 +21,7 @@
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "qemu/timer.h"
|
|
+#include "qemu/log.h"
|
|
#include "qemu/module.h"
|
|
#include "qemu/queue.h"
|
|
#include "migration/vmstate.h"
|
|
@@ -725,10 +726,14 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
|
|
bool control_td_set = 0;
|
|
uint32_t link_cnt = 0;
|
|
|
|
- while (1) {
|
|
+ do {
|
|
TRBType type;
|
|
- dma_memory_read(xhci->as, dequeue, &trb, TRB_SIZE,
|
|
- MEMTXATTRS_UNSPECIFIED);
|
|
+ if (dma_memory_read(xhci->as, dequeue, &trb, TRB_SIZE,
|
|
+ MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) {
|
|
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA memory access failed!\n",
|
|
+ __func__);
|
|
+ return -1;
|
|
+ }
|
|
le64_to_cpus(&trb.parameter);
|
|
le32_to_cpus(&trb.status);
|
|
le32_to_cpus(&trb.control);
|
|
@@ -762,7 +767,17 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
|
|
if (!control_td_set && !(trb.control & TRB_TR_CH)) {
|
|
return length;
|
|
}
|
|
- }
|
|
+
|
|
+ /*
|
|
+ * According to the xHCI spec, Transfer Ring segments should have
|
|
+ * a maximum size of 64 kB (see chapter "6 Data Structures")
|
|
+ */
|
|
+ } while (length < TRB_LINK_LIMIT * 65536 / TRB_SIZE);
|
|
+
|
|
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: exceeded maximum tranfer ring size!\n",
|
|
+ __func__);
|
|
+
|
|
+ return -1;
|
|
}
|
|
|
|
static void xhci_er_reset(XHCIState *xhci, int v)
|