DF-1106 / df1106.c
/* * DF-1106 — minimal in-kernel proof of the xhci_pci_take_controller * unbounded extended-capability pointer walk. * * The bug is in `xhci_pci_take_controller` at xhci_pci.c:398-413 and is * only reachable when an XHCI (USB 3.0) PCI controller is attached. The * default audit guest has no XHCI controller, and QEMU's emulated * `qemu-xhci` reports honest extended-capability pointers so even adding * one would not trigger the OOB walk. The realistic trigger is a * *malicious* XHCI PCI controller that lies about its eecp (via * Thunderbolt / ExpressCard / PCIe hot-plug). * * This file is *documentation only* — the source-level proof, not a * runnable trigger. * * Source trace (xhci_pci.c:398-413): * * for (eecp = XHCI_HCS0_XECP(cparams) << 2; // 16-bit field, up to 0xFFFF*4 * eecp != 0 && XHCI_XECP_NEXT(eec); // 8-bit NEXT, no bounds * eecp += XHCI_XECP_NEXT(eec) << 2) { * eec = XREAD4(sc, capa, eecp); // OOB MMIO read :401 * ... * bios_sem = XREAD1(sc, capa, eecp + XHCI_XECP_BIOS_SEM); // OOB :405 * ... * XWRITE1(sc, capa, eecp + XHCI_XECP_OS_SEM, 1); // OOB WRITE :410 * ... * bios_sem = XREAD1(sc, capa, eecp + XHCI_XECP_BIOS_SEM); // OOB :413 * } * * XREAD4/XREAD1/XWRITE1 (xhcireg.h:205-222) expand to plain * bus_space_read/write with NO bounds check. sc->sc_io_size IS recorded * at xhci_pci.c:206 but is never consulted in this loop. * * Impact: * - Page-fault panic on platforms with precise pmap_mapdev bounds. * - Infinite loop + growing eecp when an OOB read returns 0xFFFFFFFF * (XHCI_XECP_NEXT(0xFFFFFFFF) = 0xFF, never 0). * - OOB MMIO write at :410 (XWRITE1 OS_SEM). * * The fix is in fix.diff: bound `eecp + 4 <= sc->sc_io_size` in the loop * condition so any pointer past the mapped BAR terminates the walk. */ int main(void) { return 0; } |