hw/usb/hcd-ohci: Make sure that ohci_service_ed_list() cannot loop forever
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 <bea1e@proton.me> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3781 Signed-off-by: Thomas Huth <thuth@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Message-ID: <20260713160458.343323-1-thuth@redhat.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Thomas Huth committed
Jul 13, 2026 at 18:04 UTC
98e5a8eb4fb9145e9dc336b297ec14390ce88ff9
1 file changed
+10
hw/usb/hcd-ohci.c
+10
@@ -28,6 +28,7 @@
28
#include "qemu/osdep.h"
29
#include "hw/core/irq.h"
30
#include "qapi/error.h"
31
+#include "qemu/log.h"
32
#include "qemu/module.h"
33
#include "qemu/timer.h"
34
#include "hw/usb/usb.h"
@@ -1129,6 +1130,8 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head)
1130
return 0;
1131
}
1132
for (cur = head; cur && link_cnt++ < ED_LINK_LIMIT; cur = next_ed) {
1133
+ unsigned int ed_cnt = 0;
1134
+
1135
if (ohci_read_ed(ohci, cur, &ed)) {
1136
trace_usb_ohci_ed_read_error(cur);
1137
ohci_die(ohci);
@@ -1172,6 +1175,13 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head)
1175
break;
1176
}
1177
}
1178
+
1179
+ if (ed_cnt++ > ED_LINK_LIMIT) {
1180
+ qemu_log_mask(LOG_GUEST_ERROR,
1181
+ "ohci: Too many endpoint descriptors in loop\n");
1182
+ ohci_die(ohci);
1183
+ return 0;
1184
+ }
1185
}
1186
1187
if (ohci_put_ed(ohci, cur, &ed)) {