summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2016-04-18 09:11:38 +0200
committerTimothy Pearson <tpearson@raptorengineering.com>2019-11-29 20:03:49 -0600
commit159d2f182c627766edcd59ac40da59eeb375747c (patch)
treed124e1bae6f47ba1ca851477ee27160c97765a2c
parent9f6f44219b9189b007da7a09cfdefd97a327b9b5 (diff)
downloadhqemu-159d2f182c627766edcd59ac40da59eeb375747c.zip
hqemu-159d2f182c627766edcd59ac40da59eeb375747c.tar.gz
ehci: apply limit to iTD/sidt descriptors
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>
-rw-r--r--hw/usb/hcd-ehci.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 159f58d..d5c0e1c 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2011,6 +2011,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 {
@@ -2035,10 +2036,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:
@@ -2087,7 +2090,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;
OpenPOWER on IntegriCloud