DragonFlyBSD Kernel Audit
DF-1243 / 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..ee7168bb 100644
--- a/sys/dev/raid/mrsas/mrsas.c
+++ b/sys/dev/raid/mrsas/mrsas.c
@@ -3307,6 +3307,20 @@ static int mrsas_get_pd_list(struct mrsas_softc *sc)
     if (retcode == 0 && pd_list_mem->count < pd_count) {
         memset(sc->local_pd_list, 0, MRSAS_MAX_PD * sizeof(struct mrsas_pd_list));
         for (pd_index = 0; pd_index < pd_list_mem->count; pd_index++) {
+            /*
+             * deviceId is a firmware-supplied u16 (0..65535) but
+             * local_pd_list has only MRSAS_MAX_PD (256) entries.  An
+             * unchecked deviceId >= 256 corrupts ld_ids, the ev_tq
+             * taskqueue pointer, reset_flags, and load_balance_info
+             * that follow in the softc.  Skip out-of-range devices.
+             */
+            if (pd_addr->deviceId >= MRSAS_MAX_PD) {
+                device_printf(sc->mrsas_dev,
+                    "PD deviceId %u out of range (max %d), skipping\n",
+                    pd_addr->deviceId, MRSAS_MAX_PD);
+                pd_addr++;
+                continue;
+            }
             sc->local_pd_list[pd_addr->deviceId].tid = pd_addr->deviceId;
             sc->local_pd_list[pd_addr->deviceId].driveType = pd_addr->scsiDevType;
             sc->local_pd_list[pd_addr->deviceId].driveState = MR_PD_STATE_SYSTEM;