DragonFlyBSD Kernel Audit
DF-2418 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/disk/ahci/ahci.c b/sys/dev/disk/ahci/ahci.c
--- a/sys/dev/disk/ahci/ahci.c
+++ b/sys/dev/disk/ahci/ahci.c
@@ -3487,6 +3487,21 @@
 		/* Copy back the log record as a D2H register FIS. */
 		err_slot = log->err_regs.type & ATA_LOG_10H_TYPE_TAG_MASK;
 
+		/* The NCQ tag is device-controlled (5 bits, 0..31) and indexes
+		 * ap->ap_ccbs[] which is allocated with sc->sc_ncmds entries
+		 * (the NCS hardware field allows 4..32).  The non-NCQ path at
+		 * ahci.c ~line 2724 validates this bound; the NCQ path must too,
+		 * or a malicious SATA device returning a crafted log page 10h
+		 * triggers an OOB heap read (ccb_xa.state) and conditional OOB
+		 * heap write (20-byte memcpy of err_regs into ccb_xa.rfis).
+		 * See DF-2418. */
+		if (err_slot >= ap->ap_sc->sc_ncmds) {
+			kprintf("%s: read NCQ error page bad tag=%d "
+				"(ncmds=%d)\n", PORTNAME(ap),
+				err_slot, ap->ap_sc->sc_ncmds);
+			err_slot = -1;
+			goto err;
+		}
 		ccb2 = &ap->ap_ccbs[err_slot];
 		if (ccb2->ccb_xa.state == ATA_S_ONCHIP) {
 			kprintf("%s: read NCQ error page slot=%d\n",