--- a/sys/dev/raid/mps/mps_table.c +++ b/sys/dev/raid/mps/mps_table.c @@ -446,16 +446,24 @@ mps_print_sasphy0(struct mps_softc *sc, MPI2_CONFIG_PAGE_SAS_PHY_0 *buf) void mps_print_sgl(struct mps_softc *sc, struct mps_command *cm, int offset) { MPI2_SGE_SIMPLE64 *sge; MPI2_SGE_CHAIN32 *sgc; struct mps_chain *chain = NULL; char *frame; u_int i = 0, flags; + u_int seg = 0; + int framewords = sc->facts->IOCRequestFrameSize; + + if (offset < 0 || offset >= framewords) + return; frame = (char *)cm->cm_req; sge = (MPI2_SGE_SIMPLE64 *)&frame[offset * 4]; kprintf("SGL for command %p\n", cm); - hexdump(frame, 128, NULL, 0); + hexdump(frame, imin(framewords * 4, 128), NULL, 0); while (frame != NULL) { flags = le32toh(sge->FlagsLength) >> MPI2_SGE_FLAGS_SHIFT; kprintf("seg%d flags=0x%02x len=0x%06x addr=0x%016jx\n", @@ -468,15 +476,26 @@ mps_print_sgl(struct mps_softc *sc, struct mps_command *cm, int offset) MPI2_SGE_FLAGS_END_OF_BUFFER)) break; sge++; i++; + /* IOCRequestFrameSize is in dwords; a SIMPLE64 SGE is 4 dwords */ + if (++seg >= (u_int)(framewords / 4)) { + kprintf("%s: SGL walk exceeded frame bounds\n", __func__); + break; + } if (flags & MPI2_SGE_FLAGS_LAST_ELEMENT) { sgc = (MPI2_SGE_CHAIN32 *)sge; kprintf("chain flags=0x%x len=0x%x Offset=0x%x " "Address=0x%x\n", sgc->Flags, le16toh(sgc->Length), sgc->NextChainOffset, le32toh(sgc->Address)); if (chain == NULL) chain = TAILQ_FIRST(&cm->cm_chain_list); else chain = TAILQ_NEXT(chain, chain_link); + if (chain == NULL) { + kprintf("%s: chain list exhausted\n", __func__); + break; + } frame = (char *)chain->chain; sge = (MPI2_SGE_SIMPLE64 *)frame; - hexdump(frame, 128, NULL, 0); + seg = 0; + hexdump(frame, imin(framewords * 4, 128), NULL, 0); } } }