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 @@ -396,8 +396,18 @@ /* Synchronise with the BIOS if it owns the controller. */ for (eecp = XHCI_HCS0_XECP(cparams) << 2; - eecp != 0 && XHCI_XECP_NEXT(eec); + eecp != 0 && eecp + 4 <= sc->sc_io_size && XHCI_XECP_NEXT(eec); eecp += XHCI_XECP_NEXT(eec) << 2) { + /* + * Bounds-check the extended-capability pointer against the + * mapped capability registers (sc->sc_io_size recorded in + * xhci_pci_attach at xhci_pci.c:206). Without this a + * malicious controller can supply an eecp past the end of + * its BAR (XHCI_HCS0_XECP is a 16-bit field, XHCI_XECP_NEXT + * is 8-bit) and drive OOB MMIO reads at :401/:405/:413 and + * an OOB MMIO write at :410, or loop unboundedly when an OOB + * read returns 0xFFFFFFFF (NEXT=0xFF). + */ eec = XREAD4(sc, capa, eecp); if (XHCI_XECP_ID(eec) != XHCI_ID_USB_LEGACY)