diff --git a/sys/bus/u4b/controller/xhci_pci.c b/sys/bus/u4b/controller/xhci_pci.c --- a/sys/bus/u4b/controller/xhci_pci.c +++ b/sys/bus/u4b/controller/xhci_pci.c @@ -390,6 +390,8 @@ uint16_t to; uint8_t bios_sem; + uint32_t iter = 0; + cparams = XREAD4(sc, capa, XHCI_HCSPARAMS0); eec = -1; @@ -398,6 +400,19 @@ for (eecp = XHCI_HCS0_XECP(cparams) << 2; eecp != 0 && XHCI_XECP_NEXT(eec); eecp += XHCI_XECP_NEXT(eec) << 2) { + /* + * Extended-capability offsets are read from device-controlled + * MMIO and used as raw bus_space offsets. Bound them against + * the mapped BAR (capability region) and cap the traversal so + * a malicious controller cannot drive OOB MMIO R/W or spin us. + */ + if (eecp > sc->sc_io_size || + sc->sc_capa_off + eecp + sizeof(uint32_t) > sc->sc_io_size || + ++iter > 256) { + device_printf(sc->sc_bus.bdev, "xHCI extended-cap pointer " + "out of bounds or looped: 0x%x\n", eecp); + break; + } eec = XREAD4(sc, capa, eecp); if (XHCI_XECP_ID(eec) != XHCI_ID_USB_LEGACY)