DF-4089 / fix.diff
--- 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 || |