Fix DF-4250: keep sassc->maxtargets in sync with the real targets[] size. mprsas_realloc_targets() resizes sassc->targets after IOC-facts changes (mpr.c:631-634) but never updates sassc->maxtargets, which is set exactly once at attach (mpr_sas.c:760). After a second facts-changing diag reset (e.g. an IT/IR firmware-mode flip changes MaxVolumes, or a firmware update changes MaxTargets) the array is F1-sized while every consumer still bounds-checks against F0: the mprsas_add_device() PhyNum fallback + full target-struct writes (mpr_sas_lsi.c:885-965), mprsas_find_target_by_handle() (mpr_sas.c:156), the mprsas_handle_reinit() zeroing walk (mpr_sas.c:1244-1250, writes), and the CAM cpi->max_target export (mpr_sas.c:1035-1042). Verified live (rig, baseline kernel #0): the REAL mprsas_realloc_targets created the desync (maxtargets=128 over a 16-element array), the REAL mprsas_find_target_by_handle returned &targets[16..18] (foreign heap), and the REAL mprsas_handle_reinit walk clobbered 112/112 out-of-bounds struct slots (19,712 bytes past the allocation). With this fix the same rig observes maxtargets==16 after realloc and no OOB access. --- a/sys/dev/raid/mpr/mpr_sas.c +++ b/sys/dev/raid/mpr/mpr_sas.c @@ -3935,4 +3935,15 @@ panic("%s failed to alloc targets with error %d\n", __func__, ENOMEM); } + + /* + * Keep the bounds-check limit in sync with the real array size. + * Every consumer (the mprsas_add_device() PhyNum fallback in + * mpr_sas_lsi.c, mprsas_find_target_by_handle(), the reinit + * zeroing walk in mprsas_handle_reinit(), and the CAM + * cpi->max_target export) trusts sassc->maxtargets; leaving it + * stale after a size change turns all of them into out-of-bounds + * accesses. + */ + sassc->maxtargets = maxtargets; }