β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-2342

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2342 Β· 10 files
FileTypeDescriptionSize
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_testable
↓ fix.diffper-fix-DF-2342

Confirmed 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.