diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-04-19 12:10:30 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-04-19 12:10:30 +0100 |
commit | ef5d5641f5f35f64a7f150bb3593dae0c08f236d (patch) | |
tree | d902faa4504a0bfc6ed6f87bfadd2665f7e73163 | |
parent | bb97bfd90194eb3c6995b446643af4818a142805 (diff) | |
parent | a49923d2837d20510d645d3758f1ad87c32d0730 (diff) | |
download | qemu-ef5d5641f5f35f64a7f150bb3593dae0c08f236d.tar.gz qemu-ef5d5641f5f35f64a7f150bb3593dae0c08f236d.tar.bz2 qemu-ef5d5641f5f35f64a7f150bb3593dae0c08f236d.zip |
Merge remote-tracking branch 'remotes/kraxel/tags/pull-usb-20160419-1' into staging
ehci: fix (s)iTD looping issue (CVE-2015-8558) in a different way.
# gpg: Signature made Tue 19 Apr 2016 07:22:22 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg: aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>"
* remotes/kraxel/tags/pull-usb-20160419-1:
Revert "ehci: make idt processing more robust"
ehci: apply limit to iTD/sidt descriptors
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | hw/usb/hcd-ehci.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 159f58d5a0..43a8f7abcc 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1397,7 +1397,7 @@ static int ehci_process_itd(EHCIState *ehci, { USBDevice *dev; USBEndpoint *ep; - uint32_t i, len, pid, dir, devaddr, endp, xfers = 0; + uint32_t i, len, pid, dir, devaddr, endp; uint32_t pg, off, ptr1, ptr2, max, mult; ehci->periodic_sched_active = PERIODIC_ACTIVE; @@ -1489,10 +1489,9 @@ static int ehci_process_itd(EHCIState *ehci, ehci_raise_irq(ehci, USBSTS_INT); } itd->transact[i] &= ~ITD_XACT_ACTIVE; - xfers++; } } - return xfers ? 0 : -1; + return 0; } @@ -2011,6 +2010,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 +2035,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 +2089,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; |