--- a/sys/dev/raid/mpr/mpr_mapping.c +++ b/sys/dev/raid/mpr/mpr_mapping.c @@ -1241,6 +1241,36 @@ if (!topo_change->exp_handle) { map_idx = sc->num_rsvd_entries; et_entry->start_index = map_idx; + /* + * Direct-attached enclosures are mapped + * starting right after the reserved entries, + * and nothing bounds the firmware-supplied + * NumSlots against the mapping table size. + * An enclosure claiming more slots than the + * table can hold must be rejected, or the + * reservation loop below writes past the + * mapping_table allocation. Handle it the + * same way as "no space found" below. + */ + if (map_idx >= sc->max_devices || + et_entry->num_slots > + (u32)(sc->max_devices - map_idx)) { + et_entry->start_index = + MPR_MAPTABLE_BAD_IDX; + phy_change->is_processed = 1; + for (phy_idx = 0; phy_idx < + topo_change->num_entries; + phy_idx++) { + tmp_phy_change = + &topo_change->phy_details + [phy_idx]; + if (tmp_phy_change->reason == + add_code) + tmp_phy_change-> + is_processed = 1; + } + break; + } } else { map_idx = _mapping_find_enc_map_space(sc, et_entry); @@ -1392,6 +1422,36 @@ if (!topo_change->switch_dev_handle) { map_idx = sc->num_rsvd_entries; et_entry->start_index = map_idx; + /* + * Direct-attached enclosures are mapped + * starting right after the reserved entries, + * and nothing bounds the firmware-supplied + * NumSlots against the mapping table size. + * An enclosure claiming more slots than the + * table can hold must be rejected, or the + * reservation loop below writes past the + * mapping_table allocation. Handle it the + * same way as "no space found" below. + */ + if (map_idx >= sc->max_devices || + et_entry->num_slots > + (u32)(sc->max_devices - map_idx)) { + et_entry->start_index = + MPR_MAPTABLE_BAD_IDX; + port_change->is_processed = 1; + for (port_idx = 0; port_idx < + topo_change->num_entries; + port_idx++) { + tmp_port_change = + &topo_change->port_details + [port_idx]; + if (tmp_port_change->reason == + add_code) + tmp_port_change-> + is_processed = 1; + } + break; + } } else { map_idx = _mapping_find_enc_map_space(sc, et_entry);