dcavalca / rpms / qemu

Forked from rpms/qemu a year ago
Clone

Blame 0011-xhci-limit-the-number-of-link-trbs-we-are-willing-to.patch

3a13dd
From: Gerd Hoffmann <kraxel@redhat.com>
3a13dd
Date: Mon, 10 Oct 2016 12:46:22 +0200
3a13dd
Subject: [PATCH] xhci: limit the number of link trbs we are willing to process
3a13dd
3a13dd
Needed to avoid we run in circles forever in case the guest builds
3a13dd
an endless loop with link trbs.
3a13dd
3a13dd
Reported-by: Li Qiang <liqiang6-s@360.cn>
3a13dd
Tested-by: P J P <ppandit@redhat.com>
3a13dd
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
3a13dd
Message-id: 1476096382-7981-1-git-send-email-kraxel@redhat.com
3a13dd
(cherry picked from commit 05f43d44e4bc26611ce25fd7d726e483f73363ce)
3a13dd
---
3a13dd
 hw/usb/hcd-xhci.c | 10 ++++++++++
3a13dd
 1 file changed, 10 insertions(+)
3a13dd
3a13dd
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
3a13dd
index 281a2a5..8a9a31a 100644
3a13dd
--- a/hw/usb/hcd-xhci.c
3a13dd
+++ b/hw/usb/hcd-xhci.c
3a13dd
@@ -54,6 +54,8 @@
3a13dd
  * to the specs when it gets them */
3a13dd
 #define ER_FULL_HACK
3a13dd
 
3a13dd
+#define TRB_LINK_LIMIT  4
3a13dd
+
3a13dd
 #define LEN_CAP         0x40
3a13dd
 #define LEN_OPER        (0x400 + 0x10 * MAXPORTS)
3a13dd
 #define LEN_RUNTIME     ((MAXINTRS + 1) * 0x20)
3a13dd
@@ -1000,6 +1002,7 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
3a13dd
                                dma_addr_t *addr)
3a13dd
 {
3a13dd
     PCIDevice *pci_dev = PCI_DEVICE(xhci);
3a13dd
+    uint32_t link_cnt = 0;
3a13dd
 
3a13dd
     while (1) {
3a13dd
         TRBType type;
3a13dd
@@ -1026,6 +1029,9 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
3a13dd
             ring->dequeue += TRB_SIZE;
3a13dd
             return type;
3a13dd
         } else {
3a13dd
+            if (++link_cnt > TRB_LINK_LIMIT) {
3a13dd
+                return 0;
3a13dd
+            }
3a13dd
             ring->dequeue = xhci_mask64(trb->parameter);
3a13dd
             if (trb->control & TRB_LK_TC) {
3a13dd
                 ring->ccs = !ring->ccs;
3a13dd
@@ -1043,6 +1049,7 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
3a13dd
     bool ccs = ring->ccs;
3a13dd
     /* hack to bundle together the two/three TDs that make a setup transfer */
3a13dd
     bool control_td_set = 0;
3a13dd
+    uint32_t link_cnt = 0;
3a13dd
 
3a13dd
     while (1) {
3a13dd
         TRBType type;
3a13dd
@@ -1058,6 +1065,9 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
3a13dd
         type = TRB_TYPE(trb);
3a13dd
 
3a13dd
         if (type == TR_LINK) {
3a13dd
+            if (++link_cnt > TRB_LINK_LIMIT) {
3a13dd
+                return -length;
3a13dd
+            }
3a13dd
             dequeue = xhci_mask64(trb.parameter);
3a13dd
             if (trb.control & TRB_LK_TC) {
3a13dd
                 ccs = !ccs;