diff mbox series

[kirkstone,1/1] qemu: fix CVE-2020-14394

Message ID 20230809064759.1166968-1-yogita.urade@windriver.com
State New, archived
Headers show
Series [kirkstone,1/1] qemu: fix CVE-2020-14394 | expand

Commit Message

yurade Aug. 9, 2023, 6:47 a.m. UTC
QEMU: infinite loop in xhci_ring_chain_length() in hw/usb/hcd-xhci.c

Reference:
https://gitlab.com/qemu-project/qemu/-/issues/646

Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
---
 meta/recipes-devtools/qemu/qemu.inc           |  1 +
 .../qemu/qemu/CVE-2020-14394.patch            | 79 +++++++++++++++++++
 2 files changed, 80 insertions(+)
 create mode 100644 meta/recipes-devtools/qemu/qemu/CVE-2020-14394.patch
diff mbox series

Patch

diff --git a/meta/recipes-devtools/qemu/qemu.inc b/meta/recipes-devtools/qemu/qemu.inc
index 96a1cc93a5..8182342f92 100644
--- a/meta/recipes-devtools/qemu/qemu.inc
+++ b/meta/recipes-devtools/qemu/qemu.inc
@@ -97,6 +97,7 @@  SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \
            file://CVE-2023-3301.patch \
            file://CVE-2023-3255.patch \
            file://CVE-2023-2861.patch \
+	   file://CVE-2020-14394.patch \
            "
 UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar"
 
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2020-14394.patch b/meta/recipes-devtools/qemu/qemu/CVE-2020-14394.patch
new file mode 100644
index 0000000000..aff91a7355
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2020-14394.patch
@@ -0,0 +1,79 @@ 
+From effaf5a240e03020f4ae953e10b764622c3e87cc Mon Sep 17 00:00:00 2001
+From: Thomas Huth <thuth@redhat.com>
+Date: Tue, 8 Aug 2023 10:44:51 +0000
+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>
+
+CVE: CVE-2020-14394
+
+Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/effaf5a240e03020f4ae953e10b764622c3e87cc]
+
+Signed-off-by: Yogita Urade <yogita.urade@windriver.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 14bdb8967..c63a36dcc 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)
+--
+2.35.5