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