diff --git a/sys/dev/raid/mps/mps_config.c b/sys/dev/raid/mps/mps_config.c index 1111111..2222222 100644 --- a/sys/dev/raid/mps/mps_config.c +++ b/sys/dev/raid/mps/mps_config.c @@ -251,7 +251,18 @@ mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply) cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; - page = kmalloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_INTWAIT); + /* + * DF-4363: the IOC DMAs ExtPageLength/PageLength dwords into this + * buffer (mps.c mps_map_command maps cm->cm_length bytes starting at + * cm->cm_data). The buffer must be sized for cm->cm_length, not for + * the fixed MPS_MAN_PAGE10_SIZE, or a firmware page header larger + * than 0x5C walks the DMA past the allocation. Keep 0x5C as the + * minimum so the ProductSpecificInfo[] derefs below stay in bounds. + */ + if (cm->cm_length < 0x1C) { + kprintf("%s: short man page 10 (%d bytes)\n", __func__, + cm->cm_length); + error = EINVAL; + goto out; + } + page = kmalloc(MAX(cm->cm_length, MPS_MAN_PAGE10_SIZE), M_MPT2, + M_ZERO | M_INTWAIT); if (!page) { kprintf("%s: page alloc failed\n", __func__); error = ENOMEM;