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",