⬢ DragonFlyBSD Kernel Audit
DF-3914 / fix.diff
← back to finding ↓ download raw
--- 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);