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

Unbounded unvalidated PCI extended-capability loop in ehci_pci_take_controller (DoS via malicious/fuzzed controller)

Summary

BIOS-handoff loop in ehci_pci_take_controller walks linked list of PCI extended capabilities whose pointers and contents entirely device-controlled with no upper bound on iterations and no validation that eecp points past standard 0x40 config header. eecp=EHCI_HCC_EECP(cparams) is 8-bit device-authored value. Loop advances from EHCI_EECP_NEXT(eec)=(eec>>8)&0xff where eec=pci_read_config(self eecp 4) again controller-authored. No iteration counter so cycle (A.NEXT=B B.NEXT=A) or self-ref (X.NEXT=X) loops forever. No lower-bound check so controller may set eecp<0x40. Loop body also contains 5-second usb_pause_mtx busy-wait per iteration amplifying non-terminating walk into hard hang. Malicious USB controller peripheral PCIe/Thunderbolt hot-plug emulated EHCI in VM. [VERIFIED pass2: reproduced - self-referential EECP spins forever killing ssh and serial, LEGSUP variant burns the BIOS wait per iteration; 255-cap fix-validated returning after exactly 255 reads]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2335 Β· 8 files
FileTypeDescriptionSize
env.txt β€” 412 B view raw
fix.diff β€” 607 B view raw
hang.txt β€” 748 B view raw
rig β€” 4.0 KB ↓ download
run_fixed_kernel.log β€” 2.8 KB view raw
run_kernel_baseline.log β€” 172 B view raw
verdict.json β€” 2.2 KB view raw
fix.diff β€” 607 B view raw

Fix verification

not_testable
↓ fix.diffper-fix-DF-2335

Confirmed kernel references

Detail

Evidence (decisive lines)

hang.txt (baseline wedge), run_fixed_kernel.log (selfcycle RETURNED pci_reads=255; legsupspin RETURNED with bounded pause_calls), rig/dfbatch_ehci.c + gen.sh (verbatim gate), fix.diff

PoC changes

rig scenario initially zeroed the whole capability dword when scripting the BIOS semaphore byte (fixed to byte-granular writes); usb_pause_mtx interposed with a counter so the 20s-per-iteration claim is measured, not slept

Verified recommended fix

cap EECP iterations at 255 and refuse offsets below the 0x40 config header

Verdict

ehci_pci_take_controller (ehci_pci.c:504-548) verbatim rig with a scripted PCI config space: a self-referential extended-capability entry (EECP 0x50, NEXT=0x50, non-LEGSUP) makes the verbatim loop spin forever - the sysctl call never returns, ssh dies, the serial console stops being served and the QEMU process had to be SIGKILLed from the host; the linear control returns in microseconds (3 config reads). The LEGSUP variant additionally burns the 500x10ms BIOS wait per iteration (127,245 pause units observed) as the finding describes. With the iteration cap and the sub-0x40 guard the self-cycle returns after exactly 255 reads and the low-offset chain is refused. Requires a malicious/fuzzed PCI EHCI controller (physical or passed-through).