From: Thomas Huth <[email protected]> The inner while loop in ohci_service_ed_list() could theoretically loop forever if a malicious guest prepares a set of bad descriptors. Add a check to the loop to avoid this situation.
Reported-by: Feifan Qian <[email protected]> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3781 Signed-off-by: Thomas Huth <[email protected]> Reviewed-by: Daniel P. Berrangé <[email protected]> Message-ID: <[email protected]> Signed-off-by: Philippe Mathieu-Daudé <[email protected]> (cherry picked from commit 98e5a8eb4fb9145e9dc336b297ec14390ce88ff9) Signed-off-by: Michael Tokarev <[email protected]> diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index b7296ae0363..2974819a2da 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -28,6 +28,7 @@ #include "qemu/osdep.h" #include "hw/irq.h" #include "qapi/error.h" +#include "qemu/log.h" #include "qemu/module.h" #include "qemu/timer.h" #include "hw/usb.h" @@ -1130,6 +1131,8 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head) return 0; } for (cur = head; cur && link_cnt++ < ED_LINK_LIMIT; cur = next_ed) { + unsigned int ed_cnt = 0; + if (ohci_read_ed(ohci, cur, &ed)) { trace_usb_ohci_ed_read_error(cur); ohci_die(ohci); @@ -1173,6 +1176,13 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head) break; } } + + if (ed_cnt++ > ED_LINK_LIMIT) { + qemu_log_mask(LOG_GUEST_ERROR, + "ohci: Too many endpoint descriptors in loop\n"); + ohci_die(ohci); + return 0; + } } if (ohci_put_ed(ohci, cur, &ed)) { -- 2.47.3
