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]> --- hw/usb/hcd-ohci.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 40ebafb4dd9..c4a9741bd42 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -28,6 +28,7 @@ #include "qemu/osdep.h" #include "hw/core/irq.h" #include "qapi/error.h" +#include "qemu/log.h" #include "qemu/module.h" #include "qemu/timer.h" #include "hw/usb/usb.h" @@ -1129,6 +1130,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); @@ -1172,6 +1175,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.55.0
