Uninitialized kernel stack read via short/malformed CH341 control responses
Summary
uchcom_read_reg() and uchcom_get_version() declare 8-byte stack buffer without initializing issue vendor control-IN request with USB_SHORT_XFER_OK then unconditionally consume buf[0]/buf[1] as register values without checking how many bytes device returned or whether transfer errored. usbd_do_request_flags only copies received byte count so short/zero-length completion leaves buf[temp..7] untouched. Tainted bytes reach sc->sc_msr returned to userspace via TIOCMGET modem-status bits and printed verbatim to kernel log when USB_DEBUG compiled in. uchcom_ctrl_read discards usb_error_t return. Malicious CH341 device returning short/zero-byte response leaks up to 4 bits kernel stack per TIOCMGET poll + 2 raw bytes to dmesg. [VERIFIED pass2: reproduced - zero control responses leave buf uninitialized with raw stack bytes printed on USB_DEBUG and 4 TIOCMGET bits from the undelivered byte; bzero fix-validated]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2342 Β· 10 files| File | Type | Description | Size | |
|---|---|---|---|---|
| build.log | β | 1.2 KB | view raw | |
| build.sh | β | 91 B | view raw | |
| env.txt | β | 412 B | view raw | |
| fix.diff | β | 498 B | view raw | |
| run.log | β | 963 B | view raw | |
| run.sh | β | 115 B | view raw | |
| run_fixed.log | β | 934 B | view raw | |
| uchcom_rig.c | β | 5.3 KB | view raw | |
| verdict.json | β | 2.1 KB | view raw | |
| fix.diff | β | 498 B | view raw |
Fix verification
not_testableConfirmed kernel references
Detail
Exploit chain
malicious CH341 returns short/zero-length control responses; any TIOCMGET poll on the open tty reads 4 bits of kernel stack per call; 2 raw bytes per poll on USB_DEBUG builds
Evidence (decisive lines)
run.log (zerolen/short1: DPRINTF poison bytes + sc_msr nibbles), run_fixed.log (0x06->0x00 deterministic), fix.diff
PoC changes
wValue/wIndex/wLength shimmed as 2-byte arrays so the verbatim USETW macro text compiles; ucom sc_parent wired so uchcom_cfg_get_status runs verbatim
Verified recommended fix
bzero the response buffers before the control request
Verdict
uchcom_read_reg/uchcom_get_version (uchcom.c:413-442) verbatim rig: the shimmed ucom_cfg_do_request models a CH341 that completes the 8-byte vendor read with zero (or one) data bytes and returns success; the verbatim consumers read buf[0]/buf[1] unconditionally. With a poisoned kernel stack (0xA5) the debug print shows the raw uninitialized bytes (0x06->0xA5, 0x07->0xA5), and uchcom_convert_status maps ~buf[0]&0x0F into the four TIOCMGET-visible modem-status bits (sc_msr=0xaa: nibble 0xA is pure poison). The 1-byte variant leaks the second byte via the XOR path. With the bzero both channels carry deterministic zeros. Requires a malicious CH341 device; dmesg print needs a USB_DEBUG kernel, the TIOCMGET nibble does not.
No comments yet.