ubser_attach GET_NUMSER: first bus transaction is a synchronous 5000 ms-timeout vendor control read on the per-bus USB explore thread β an evil BWCT-string adapter pins bus-wide device enumeration ~5 s per insertion (or ~4.9 s with every request succeeding)
Summary
The attach's first act is the port-count read at the 5000ms default on the explore thread: a silent device pins enumeration the full 5s then aborts verbatim; a just-under-timeout device pins ~4.9s with every request SUCCEEDING and attach continuing. Verbatim-extraction harness: 4916/4917ms silent (verbatim error + abort), 4812/4807ms slow-answer (verbatim 'found 4 serials'); 1000ms-bound fix -> 1009/891ms. Family minimum (one attach request; cf. DF-5359/5407/5488/5505).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5516 Β· 14 files| File | Type | Description | Size | |
|---|---|---|---|---|
| ub5516attachstall_harness.c | β | 7.4 KB | view raw | |
| Makefile | β | 143 B | β download | |
| build.sh | β | 143 B | view raw | |
| run.sh | β | 145 B | view raw | |
| build.log | β | 7.1 KB | view raw | |
| run.log | β | 1.1 KB | view raw | |
| run.2.log | β | 1.1 KB | view raw | |
| run.fixed.log | β | 910 B | view raw | |
| fix_build.log | β | 840 B | view raw | |
| env.txt | β | 491 B | view raw | |
| fix.diff | β | 608 B | view raw | |
| VERDICT.md | β | 3.4 KB | β raw | |
| manifest.json | β | 1.1 KB | view raw | |
| verdict.json | β | 4.6 KB | view raw |
DF-5516 VERDICT β reproduced (mechanism level, verbatim production block)
Finding
ubser_attach() (ubser.c:223-299) issues its FIRST bus transaction
synchronously on the attaching thread β the per-bus USB explore (hub event)
thread: the VENDOR_GET_NUMSER control read at ubser.c:243-251 with
USB_DEFAULT_TIMEOUT = 5000 ms (usbdi.h:87). An evil adapter is one
firmware string away from this path: ubser_probe (ubser.c:215-217) matches
manufacturer string "BWCT" + bInterfaceClass 0xff + bInterfaceSubClass 0x00.
A device that NAKs the data stage pins bus-wide device enumeration for the
full 5 s per insertion; a device that answers at just-under-timeout pins
~4.9 s while every request SUCCEEDS (no error visible anywhere).
Reproduction (verbatim extraction)
build.sh sed-extracts ubser.c:242-262 unmodified from the guest's
md5-gated /usr/src into ub5516_block.c and compiles it inside the
simulated attach; the production driver file is also included whole (for
types/constants; registration neutered). Only the EP0 sink
(usbd_do_request_flags, matching usbdi.h:508-510) and device_printf are
models; usbd_errstr is the real kernel symbol. The fragment's
goto detach (ubser.c:257) binds to a local label standing in for the
production label at ubser.c:296-298.
Measured (run.log / run.2.log, hz=100):
| phase | scenario | measured |
|---|---|---|
| A | silent evil device (NAK until timeout) | explore-thread occupancy 4916/4917 ms; verbatim error path fires ("failed to get number of serial ports: USB_ERR_TIMEOUT" via the real usbd_errstr) and the verbatim goto detach aborts attach |
| B | slow-answer device (answers at 4900 ms, claims 4 ports) | occupancy 4812/4807 ms; request SUCCEEDS, verbatim "found 4 serials", attach CONTINUES β invisible variant |
| C (fixed) | timeout bounded to 1000 ms (fix.diff) | occupancy 1009 ms fail-fast (891 ms slow-answer) β pin GONE |
During the pin no other device on that bus can finish enumerating (family mechanism, DF-5359/DF-5407/DF-5488/DF-5505); repeatable at will by re-insertion.
Fix validation
fix.diff (ubser.c:251: USB_DEFAULT_TIMEOUT -> 1000) applied to the
guest's /usr/src copy; block re-extracted (now at 244-264 due to the +2-line
comment); harness rebuilt -Werror clean; rerun: 1009 ms fail-fast vs
4916 ms baseline (run.fixed.log). Guest tree restored and md5-verified
(85afa08fa4f618c9288a6dca75d9e671). git apply --check passes against the
audited host repo.
Impact
Availability only (per-bus enumeration stall, ~5 s per evil-BWCT insertion; family minimum β exactly one attach request, cf. DF-5505 ucycom Low, uvisor 2x5 s DF-5488 Low, uipaq 12.8 s DF-5359 Low, uplcom ~70 s DF-5407 Medium). Low per family calibration.
Honest scope notes
- Mechanism level: no physical BWCT adapter exists for the guest; the EP0 sink timing is modeled, the attach block, request fields, error path and abort path are production code verbatim.
- build.sh's md5 gate correctly refuses to run on a patched tree; the fixed-build extraction (+2 line shift) is documented in README.md.
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
fixedfix.diff applied to the guest's /usr/src ubser.c (guest patch(1), hunk @246 offset -1); the block re-extracted from the patched tree (now 244-264) and the same harness rebuilt -Werror-clean and re-run: silent-device occupancy 1009 ms fail-fast vs 4916 ms baseline (slow-answer 891 ms vs 4812 ms) -- the enumeration pin is gone and a live adapter still answers a port-count read in milliseconds. git apply --check passes on the audited repo; guest tree restored and md5-verified.
fix.diff; fix_build.log (RC=0); run.fixed.log ('UB5516[A]: explore-thread occupancy 1009 ms', 'UB5516[B]: ... 891 ms'); VERDICT.md 'Fix validation' section
Confirmed kernel references
Detail
Exploit chain
attacker physically inserts an evil USB adapter presenting manufacturer string 'BWCT' + bInterfaceClass 0xff + bInterfaceSubClass 0x00 -> uhub hands it to ubser_attach on the per-bus USB explore thread -> the device NAKs (or slowly answers) the VENDOR_GET_NUMSER data stage -> the synchronous 5 s-timeout request pins bus-wide device enumeration ~5 s per insertion (or ~4.9 s with every request succeeding); repeatable at will by re-insertion
Evidence (decisive lines)
run.log/run.2.log: 'UB5516[A]: explore-thread occupancy 4916/4917 ms; attach ABORT via verbatim `goto detach'' and 'UB5516[B]: ... 4812/4807 ms; attach CONTINUES' with the request succeeding; run.fixed.log: 'occupancy 1009 ms' (fix validated); build.log: verbatim extraction echoed + -Werror-clean build
PoC changes
No seed PoC existed; authored from scratch on the DF-5488/DF-5505 verbatim-extraction pattern. Bring-up fixes: (1) the harness must MODULE_DEPEND on ucom as well (ubser.c's ubser_detach references ucom_detach, unresolved at kldload without it); (2) the verbatim block's `goto detach' (ubser.c:257) needs a local label standing in for ubser.c:296; (3) build.sh's md5 gate must be bypassed (documented) for the fixed build, whose block shifts to lines 244-264.
Verified recommended fix
Bound the enumeration-time port-count read: 1000 ms instead of USB_DEFAULT_TIMEOUT at ubser.c:251 (full diff in fix.diff; validated: 4916 ms -> 1009 ms).
Verdict
Mechanism-level reproduction with the production block verbatim (DF-5488/DF-5505 evidence class): ubser.c:242-262 -- the GET_NUMSER block of ubser_attach, sed-extracted unmodified from the md5-gated guest tree -- runs inside the simulated attach with only the EP0 sink modeled. ubser_probe (ubser.c:215-217) hands attach to any device whose firmware says manufacturer='BWCT' with a vendor-specific interface, and the FIRST bus transaction is the synchronous GET_NUMSER with USB_DEFAULT_TIMEOUT=5000 ms (usbdi.h:87) on the per-bus USB explore thread. Measured (hz=100): a silent evil adapter pinned the (simulated) explore thread 4916/4917 ms per insertion before the verbatim error path aborted attach ('failed to get number of serial ports: USB_ERR_TIMEOUT' via the real usbd_errstr, verbatim goto detach at ubser.c:257); a slow-answer evil adapter made the request SUCCEED at 4900 ms and attach CONTINUE (verbatim 'found 4 serials') while still pinning 4812/4807 ms -- no error visible anywhere. Every other device on that bus waits out the pin (family mechanism). fix.diff (ubser.c:251: USB_DEFAULT_TIMEOUT -> 1000) applied on the guest, block re-extracted (+2-line shift), harness rebuilt and re-run: 1009 ms fail-fast (891 ms slow-answer) -- pin GONE; tree restored md5-verified.
No comments yet.