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