DragonFlyBSD Kernel Audit
DF-2336 / fix.diff
← back to finding ↓ download raw
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)