diff --git a/sys/dev/raid/mpr/mpr_sas.c b/sys/dev/raid/mpr/mpr_sas.c index 1111111..2222222 100644 --- a/sys/dev/raid/mpr/mpr_sas.c +++ b/sys/dev/raid/mpr/mpr_sas.c @@ -3908,14 +3908,25 @@ mprsas_check_id(struct mprsas_softc *sassc, int id) void mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets) { struct mprsas_softc *sassc; struct mprsas_lun *lun, *lun_tmp; struct mprsas_target *targ; - int i; + int i; + + /* + * DF-3800: the targets array must track the *current* IOC facts. + * Callers previously passed the pre-reset ("saved") facts while the + * mapping layer was rebuilt from the new facts, so mapping-derived + * target ids could index past the array (heap OOB write) and, in the + * opposite direction, CAM target ids could index past the shrunken + * mapping_table. + */ + maxtargets = sc->facts->MaxTargets + sc->facts->MaxVolumes; sassc = sc->sassc; /* * The number of targets is based on IOC Facts, so free all of * the allocated LUNs for each target and then the target buffer * itself. */ - for (i=0; i< maxtargets; i++) { + for (i = 0; i < sassc->maxtargets; i++) { targ = &sassc->targets[i]; SLIST_FOREACH_MUTABLE(lun, &targ->luns, lun_link, lun_tmp) { kfree(lun, M_MPR); } @@ -3930,9 +3941,11 @@ mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets) sassc->targets = kmalloc(sizeof(struct mprsas_target) * maxtargets, M_MPR, M_WAITOK|M_ZERO); if (!sassc->targets) { panic("%s failed to alloc targets with error %d\n", __func__, ENOMEM); } + sassc->maxtargets = maxtargets; } diff --git a/sys/dev/raid/mpr/mpr.c b/sys/dev/raid/mpr/mpr.c index 3333333..4444444 100644 --- a/sys/dev/raid/mpr/mpr.c +++ b/sys/dev/raid/mpr/mpr.c @@ -629,8 +629,9 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching) */ if (reallocating) { mpr_iocfacts_free(sc); - mprsas_realloc_targets(sc, saved_facts.MaxTargets + - saved_facts.MaxVolumes); + /* DF-3800: resize to the CURRENT facts; the helper also + * updates sassc->maxtargets. */ + mprsas_realloc_targets(sc, sc->facts->MaxTargets + + sc->facts->MaxVolumes); } diff --git a/sys/dev/raid/mpr/mpr_sas_lsi.c b/sys/dev/raid/mpr/mpr_sas_lsi.c index 5555555..6666666 100644 --- a/sys/dev/raid/mpr/mpr_sas_lsi.c +++ b/sys/dev/raid/mpr/mpr_sas_lsi.c @@ -905,6 +905,12 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u16 flag) goto out; } } + /* DF-3800 defense-in-depth: mapping ids must honor the target array. */ + if (id >= sassc->maxtargets) { + mpr_dprint(sc, MPR_ERROR, "mapping id %d exceeds maxtargets %d\n", + id, sassc->maxtargets); + error = ENXIO; + goto out; + } mpr_dprint(sc, MPR_MAPPING, "%s: Target ID for added device is %d.\n", __func__, id);