⬢ DragonFlyBSD Kernel Audit
DF-4089 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/raid/mps/mps_sas_lsi.c
+++ b/sys/dev/raid/mps/mps_sas_lsi.c
@@ -125,7 +125,7 @@
     MPI2_EVENT_NOTIFICATION_REPLY *event)
 {
 	struct mps_fw_event_work *fw_event;
-	u16 sz;
+	u32 sz, copy_len;
 
 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
 	mps_print_evt_sas(sc, event);
@@ -137,7 +137,27 @@
 		kprintf("%s: allocate failed for fw_event\n", __func__);
 		return;
 	}
-	sz = le16toh(event->EventDataLength) * 4;
+	copy_len = le16toh(event->EventDataLength) * 4;
+	sz = copy_len;
+	/* The mapping engine (mps_mapping.c) walks PHY[] and
+	 * ConfigElement[] by the firmware-supplied NumEntries /
+	 * NumElements without any frame-length bound; size the copy
+	 * for the maximum walk so those walks cannot read past the
+	 * allocation. */
+	switch (event->Event) {
+	case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
+		sz = imax(sz, offsetof(Mpi2EventDataSasTopologyChangeList_t,
+		    PHY) + ((Mpi2EventDataSasTopologyChangeList_t *)
+		    event->EventData)->NumEntries *
+		    sizeof(Mpi2EventSasTopoPhyEntry_t));
+		break;
+	case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
+		sz = imax(sz, offsetof(Mpi2EventDataIrConfigChangeList_t,
+		    ConfigElement) + ((Mpi2EventDataIrConfigChangeList_t *)
+		    event->EventData)->NumElements *
+		    sizeof(Mpi2EventIrConfigElement_t));
+		break;
+	}
 	fw_event->event_data = kmalloc(sz, M_MPT2, M_ZERO|M_INTWAIT);
 	if (!fw_event->event_data) {
 		kprintf("%s: allocate failed for event_data\n", __func__);
@@ -145,7 +165,7 @@
 		return;
 	}
 
-	bcopy(event->EventData, fw_event->event_data, sz);
+	bcopy(event->EventData, fw_event->event_data, copy_len);
 	fw_event->event = event->Event;
 	if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
 	    event->Event == MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE ||