DragonFlyBSD Kernel Audit
DF-1242 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/raid/mrsas/mrsas.c b/sys/dev/raid/mrsas/mrsas.c
index 38a2742c..55fbf36b 100644
--- a/sys/dev/raid/mrsas/mrsas.c
+++ b/sys/dev/raid/mrsas/mrsas.c
@@ -1267,6 +1267,30 @@ static int mrsas_complete_cmd(struct mrsas_softc *sc)
     while((desc_val.u.low != 0xFFFFFFFF) && (desc_val.u.high != 0xFFFFFFFF)) 
     {
         smid = reply_desc->SMID;
+        /*
+         * SMID comes from DMA (firmware).  smid==0 yields index -1; smid
+         * above max_fw_cmds is a wild OOB into mpt_cmd_list[].  Both
+         * produce a garbage cmd_mpt whose deref (io_request, ccb_ptr,
+         * sync_cmd_idx) corrupts or crashes the kernel.  Drop the entry.
+         */
+        if (smid == 0 || smid > sc->max_fw_cmds) {
+            device_printf(sc->mrsas_dev,
+                "invalid SMID %u (max %u), dropping reply\n",
+                smid, sc->max_fw_cmds);
+            sc->last_reply_idx++;
+            if (sc->last_reply_idx >= sc->reply_q_depth)
+                sc->last_reply_idx = 0;
+            desc->Words = ~((uint64_t)0x00);
+            if (!sc->last_reply_idx)
+                desc = sc->reply_desc_mem;
+            else
+                desc++;
+            reply_desc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
+            desc_val.word = desc->Words;
+            reply_descript_type =
+                reply_desc->ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+            continue;
+        }
         cmd_mpt = sc->mpt_cmd_list[smid -1];
         scsi_io_req = (MRSAS_RAID_SCSI_IO_REQUEST *)cmd_mpt->io_request;