* [PATCH] hw/usb/host-libusb: Avoid assertion on invalid altsetting
@ 2026-08-12 9:24 dongwon.kim
2026-10-28 5:37 ` Junjie Cao
0 siblings, 1 reply; 2+ messages in thread
From: dongwon.kim @ 2026-08-12 9:24 UTC (permalink / raw)
To: qemu-devel
From: Liang1 Yang <liang1.yang@intel.com>
Log warning and skip the interface instead of asserting in qemu
host-libusb when there is invalid altsetting index during fast
USB device hotplug/unplug.
This is to prevent guest vm from crashing which is caused by
QEMU task abort.
Signed-off-by: Liang1 Yang <liang1.yang@intel.com>
Signed-off-by: Dongwon Kim <dongwon.kim@intel.com>
---
hw/usb/host-libusb.c | 37 +++++++++++++++++++++++++++++++++++--
1 file changed, 35 insertions(+), 2 deletions(-)
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index 629505c6d3..56cfc90f9b 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -884,10 +884,32 @@ static void usb_host_ep_update(USBHostDevice *s)
if (rc != 0) {
return;
}
+
+ /* Log and skip if configuration is NULL or has no interfaces */
+ if (!conf || conf->bNumInterfaces == 0) {
+ warn_report("usb-host: ignoring invalid configuration "
+ "for device %s (bus=%03d, addr=%03d)",
+ udev->product_desc, s->bus_num, s->addr);
+
+ if (conf) {
+ libusb_free_config_descriptor(conf);
+ }
+
+ return;
+ }
+
trace_usb_host_parse_config(s->bus_num, s->addr,
conf->bConfigurationValue, true);
for (i = 0; i < conf->bNumInterfaces; i++) {
+ if (conf->interface[i].num_altsetting == 0 ||
+ !conf->interface[i].altsetting) {
+ warn_report("usb-host: skipping interface (index %d) with no "
+ "alternate settings on %s (bus=%03d, addr=%03d)",
+ i, udev->product_desc, s->bus_num, s->addr);
+ continue;
+ }
+
/*
* The udev->altsetting array indexes alternate settings
* by the interface number. Get the 0th alternate setting
@@ -897,8 +919,19 @@ static void usb_host_ep_update(USBHostDevice *s)
intf = &conf->interface[i].altsetting[0];
alt = udev->altsetting[intf->bInterfaceNumber];
- if (alt != 0) {
- assert(alt < conf->interface[i].num_altsetting);
+ if (alt > 0) {
+ if (alt >= conf->interface[i].num_altsetting) {
+ /*
+ * libusb reports a temporary invalid altsetting index during
+ * fast hotplug/unplug. Instead of aborting, log a warning and
+ * skip the interface.
+ */
+ warn_report("usb-host: ignoring out-of-bounds altsetting=%d "
+ "for interface %d (index %d) on %s (bus=%03d, addr=%03d)",
+ alt, intf->bInterfaceNumber, i,
+ udev->product_desc, s->bus_num, s->addr);
+ continue;
+ }
intf = &conf->interface[i].altsetting[alt];
}
--
2.43.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] hw/usb/host-libusb: Avoid assertion on invalid altsetting
2026-08-12 9:24 [PATCH] hw/usb/host-libusb: Avoid assertion on invalid altsetting dongwon.kim
@ 2026-10-28 5:37 ` Junjie Cao
0 siblings, 0 replies; 2+ messages in thread
From: Junjie Cao @ 2026-10-28 5:37 UTC (permalink / raw)
To: dongwon.kim; +Cc: liang1.yang, qemu-devel, thuth, marcandre.lureau, junjie.cao
On Wed, 12 Aug 2026 02:24:03 -0700, dongwon.kim@intel.com wrote:
> Log warning and skip the interface instead of asserting in qemu
> host-libusb when there is invalid altsetting index during fast
> USB device hotplug/unplug.
Hi Dongwon, Liang,
The out-of-range alt does not come from libusb. It is QEMU's own
udev->altsetting[], written by usb_host_set_interface() when the guest
selects an alternate setting and only cleared in
usb_host_claim_interfaces() on SET_CONFIGURATION. usb_host_open() runs
usb_host_ep_update() before either of those, so when a different device
shows up on the same usb-host instance, the values left behind by the
previous device are checked against the new device's descriptors.
Reproduced on master with -device usb-host,hostbus=3,hostport=4 and a
Debian 12 guest on qemu-xhci: an Arkmicro 18ec:3399 UVC camera, guest
selects interface 1 alt 11 through usbfs, camera unplugged, a Jieli
4c4a:4155 UAC device (interface 1 has two alternate settings) plugged
into the same port. QEMU aborts at host-libusb.c:910 while opening the
second device.
Skipping the interface hides the assert but keeps the stale value, and a
stale value that happens to be in range is not caught at all: it picks
the endpoints of the wrong alternate setting. Clearing udev->altsetting[]
in usb_host_open() before usb_host_ep_update(), the way
usb_host_claim_interfaces() does, removes the cause. The guest has not
selected anything on the new device yet, so zero is the right content,
and the array is written again only after
libusb_set_interface_alt_setting() succeeds, so the assert can stay.
udev->ninterfaces and udev->configuration go stale the same way; nothing
in usb-host reads them, but moving the three resets from
usb_host_claim_interfaces() into a helper called from both places keeps
them together. With udev->altsetting[] cleared the sequence above
enumerates the second device, snd-usb-audio and usbhid bind to it and
its own SET_INTERFACE round trips go through.
> + warn_report("usb-host: ignoring out-of-bounds altsetting=%d "
> + "for interface %d (index %d) on %s (bus=%03d, addr=%03d)",
> + alt, intf->bInterfaceNumber, i,
> + udev->product_desc, s->bus_num, s->addr);
usb_host_open() fills udev->product_desc after usb_host_ep_update(), so
this names the previous device. With the patch rebased onto master the
sequence above prints
usb-host: ignoring out-of-bounds altsetting=11 for interface 1 (index 1)
on USB2.0 PC CAMERA (bus=003, addr=014)
for the audio device.
> + /* Log and skip if configuration is NULL or has no interfaces */
> + if (!conf || conf->bNumInterfaces == 0) {
libusb_get_active_config_descriptor() sets *config whenever it returns
0, so !conf cannot happen, and bNumInterfaces == 0 already falls through
the loop.
The patch also no longer applies on master: e1b7f5e2a6 ("usb-host:
validate interface number before indexing altsetting") changed the same
loop, and conf is a g_autoptr there since 322894eed3, so the explicit
libusb_free_config_descriptor() in the new early return would be a
double free. A v2 should carry
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3189 and
Cc: qemu-stable@nongnu.org, the assert is reachable from 9.1.0 as
reported there.
Thanks,
Junjie
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-28 5:38 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-12 9:24 [PATCH] hw/usb/host-libusb: Avoid assertion on invalid altsetting dongwon.kim
2026-10-28 5:37 ` Junjie Cao
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.