Commit e1b7f5e2a6 for qemu.org
commit e1b7f5e2a6715c4f7e9f5a4356101dc45b24b64f
Author: Junjie Cao <junjie.cao@intel.com>
Date: Mon Oct 5 00:46:25 2026 -0500
usb-host: validate interface number before indexing altsetting
usb_host_ep_update() indexes USBDevice.altsetting with the interface
number supplied by the active configuration descriptor. A descriptor
with bInterfaceNumber >= USB_MAX_INTERFACES reads past that array while
the host device is opened. Skip such interfaces before the lookup.
Record the descriptor's interface number on its endpoints as well. The
loop index identifies the descriptor's position in the configuration,
which need not equal bInterfaceNumber.
Fixes: 0dbe4768b95e ("usb-host: use correct altsetting in usb_host_ep_update")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3975
Cc: qemu-stable@nongnu.org
Signed-off-by: Junjie Cao <junjie.cao@intel.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20261005054626.131577-2-junjie.cao@linux.dev>
Signed-off-by: Thomas Huth <thuth@redhat.com>
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index 629505c6d3..fd4a16ee8a 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -895,6 +895,11 @@ static void usb_host_ep_update(USBHostDevice *s)
* then correct the alternate setting value if necessary.
*/
intf = &conf->interface[i].altsetting[0];
+ if (intf->bInterfaceNumber >= USB_MAX_INTERFACES) {
+ trace_usb_host_parse_error(s->bus_num, s->addr,
+ "invalid interface number");
+ continue;
+ }
alt = udev->altsetting[intf->bInterfaceNumber];
if (alt != 0) {
@@ -930,7 +935,7 @@ static void usb_host_ep_update(USBHostDevice *s)
usb_ep_set_max_packet_size(udev, pid, ep,
endp->wMaxPacketSize);
usb_ep_set_type(udev, pid, ep, type);
- usb_ep_set_ifnum(udev, pid, ep, i);
+ usb_ep_set_ifnum(udev, pid, ep, intf->bInterfaceNumber);
usb_ep_set_halted(udev, pid, ep, 0);
#ifdef HAVE_STREAMS
if (type == LIBUSB_TRANSFER_TYPE_BULK &&