usb: a configuration block is as long as the device says it is

The driver read the first 512 bytes of a configuration block into a fixed
buffer and parsed those. The block's length is the device's own choice
(wTotalLength, a u16), so anything larger was silently cut: interfaces past
the cut did not exist as far as the host was concerned, while the
SET_CONFIGURATION that follows still configured the device for all of them.
A headset is 500-900 bytes, a UVC webcam 1-3 KB, a multifunction printer
600+.

Now allocated at the declared length, so the ceiling is the field's u16 —
the specification's number rather than one of ours. A block shorter than its
own 9-byte header is refused rather than trusted.

The bring-up line reports the declared length and the bytes actually read,
so a truncation can never again be invisible, and usb-large-descriptor
asserts they match with a backreference.

That case has an honest limit, recorded in its comment: QEMU cannot produce
a block over 512 bytes. The boot keyboard, mouse and stick are 34-44, and
the largest device available is usb-audio in multi-channel mode at 211 —
which is exactly why the suite never caught this, and why it cannot now
reproduce the original trigger. What it does catch is the class: any clamp
below the attached device's block fails it, verified by pinning the buffer
to 128 and watching "config block 211 bytes, read 128" turn the case red.

Suite 115 -> 116.
This commit is contained in:
Daniel Samson
2026-08-08 11:53:01 +01:00
parent 69fbef40c0
commit 6328823ef1
4 changed files with 42 additions and 8 deletions
+22
View File
@@ -674,6 +674,28 @@ CASES = [
r"(?=.*hub slot \d+ port \d+ device:.*0x0627)"
r"(?=.*usb-hid-keyboard: ok \(device 3)",
"fail": r"DANOS-TEST-RESULT: FAIL"},
# The driver must never truncate a configuration block. Its size is the DEVICE's
# choice (wTotalLength, a u16); the driver used to read the first 512 bytes into a
# fixed buffer and parse those, so interfaces past the cut did not exist while
# SET_CONFIGURATION still configured the device for all of them.
#
# The backreference is the assertion: declared length and bytes read must match.
#
# Honest limit: QEMU cannot produce a block over 512 bytes. Its boot keyboard,
# mouse and stick are 34-44, and the largest device on offer is usb-audio in
# multi-channel mode at 211 — which is why the suite never saw the original bug,
# and why it cannot now reproduce that exact trigger. What this case does catch is
# the class: any clamp below the attached device's block size fails it, verified
# by pinning the buffer to 128 and watching it go red. A real headset (500-900
# bytes), UVC webcam (1-3 KB) or multifunction printer trips the 512 itself.
{"name": "usb-large-descriptor",
"build_case": "usb-hid",
"smp": 4,
"timeout": 150,
"qemu_extra": ["-device", "qemu-xhci,id=xhci2",
"-device", "usb-audio,bus=xhci2.0,port=1,multi=on"],
"expect": r"(?s)(?=.*usb-xhci-bus: config block (\d\d\d+) bytes, read \1)",
"fail": r"DANOS-TEST-RESULT: FAIL"},
# USB mass storage end to end: the boot usb-storage device (the FAT32 image,
# which has a real 0x55AA boot sector) is enough — the manager spawns
# usb-storage, which opens the device, runs the Bulk-Only / SCSI bring-up,