60 lines
2.0 KiB
Diff
60 lines
2.0 KiB
Diff
|
From: Gerd Hoffmann <kraxel@redhat.com>
|
||
|
Date: Mon, 18 Apr 2016 09:11:38 +0200
|
||
|
Subject: [PATCH] ehci: apply limit to iTD/sidt descriptors
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
Commit "156a2e4 ehci: make idt processing more robust" tries to avoid a
|
||
|
DoS by the guest (create a circular iTD queue and let qemu ehci
|
||
|
emulation run in circles forever). Unfortunately this has two problems:
|
||
|
First it misses the case of siTDs, and second it reportedly breaks
|
||
|
FreeBSD.
|
||
|
|
||
|
So lets go for a different approach: just count the number of iTDs and
|
||
|
siTDs we have seen per frame and apply a limit. That should really
|
||
|
catch all cases now.
|
||
|
|
||
|
Reported-by: 杜少博 <dushaobo@360.cn>
|
||
|
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||
|
(cherry picked from commit 1ae3f2f178087711f9591350abad133525ba93f2)
|
||
|
---
|
||
|
hw/usb/hcd-ehci.c | 6 +++++-
|
||
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
||
|
|
||
|
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
|
||
|
index c40013e..b75488b 100644
|
||
|
--- a/hw/usb/hcd-ehci.c
|
||
|
+++ b/hw/usb/hcd-ehci.c
|
||
|
@@ -2003,6 +2003,7 @@ static int ehci_state_writeback(EHCIQueue *q)
|
||
|
static void ehci_advance_state(EHCIState *ehci, int async)
|
||
|
{
|
||
|
EHCIQueue *q = NULL;
|
||
|
+ int itd_count = 0;
|
||
|
int again;
|
||
|
|
||
|
do {
|
||
|
@@ -2027,10 +2028,12 @@ static void ehci_advance_state(EHCIState *ehci, int async)
|
||
|
|
||
|
case EST_FETCHITD:
|
||
|
again = ehci_state_fetchitd(ehci, async);
|
||
|
+ itd_count++;
|
||
|
break;
|
||
|
|
||
|
case EST_FETCHSITD:
|
||
|
again = ehci_state_fetchsitd(ehci, async);
|
||
|
+ itd_count++;
|
||
|
break;
|
||
|
|
||
|
case EST_ADVANCEQUEUE:
|
||
|
@@ -2079,7 +2082,8 @@ static void ehci_advance_state(EHCIState *ehci, int async)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
- if (again < 0) {
|
||
|
+ if (again < 0 || itd_count > 16) {
|
||
|
+ /* TODO: notify guest (raise HSE irq?) */
|
||
|
fprintf(stderr, "processing error - resetting ehci HC\n");
|
||
|
ehci_reset(ehci);
|
||
|
again = 0;
|