DragonFlyBSD Kernel Audit
DF-1106 / 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
@@ -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)