--- a/sys/dev/raid/mpr/mpr_table.c +++ b/sys/dev/raid/mpr/mpr_table.c @@ -537,7 +537,8 @@ mpr_print_sgl(struct mpr_softc *sc, struct mpr_command *cm, int offset) MPI2_SGE_SIMPLE64 *sge; MPI2_REQUEST_HEADER *req; struct mpr_chain *chain = NULL; char *frame; u_int i = 0, flags, length; + u_int seg = 0; req = (MPI2_REQUEST_HEADER *)cm->cm_req; frame = (char *)cm->cm_req; @@ -545,6 +546,7 @@ mpr_print_sgl(struct mpr_softc *sc, struct mpr_command *cm, int offset) sge = (MPI2_SGE_SIMPLE64 *)&frame[offset * 4]; kprintf("SGL for command %p\n", cm); hexdump(frame, 128, NULL, 0); + seg = 0; while ((frame != NULL) && (!(cm->cm_flags & MPR_CM_FLAGS_SGE_SIMPLE))) { flags = ieee_sge->Flags; length = le32toh(ieee_sge->Length); @@ -553,14 +555,22 @@ mpr_print_sgl(struct mpr_softc *sc, struct mpr_command *cm, int offset) if (flags & MPI25_IEEE_SGE_FLAGS_END_OF_LIST) break; ieee_sge++; i++; + /* a frame is at most 128 bytes = 8 16-byte SGEs; 32 is a hard stop */ + if (++seg >= 32) { + kprintf("%s: SGL walk exceeded frame bounds\n", __func__); + break; + } if (flags & MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT) { 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; ieee_sge = (MPI2_IEEE_SGE_SIMPLE64 *)frame; + seg = 0; hexdump(frame, 128, NULL, 0); } } @@ -573,6 +583,10 @@ mpr_print_sgl(struct mpr_softc *sc, struct mpr_command *cm, int offset) MPI2_SGE_FLAGS_END_OF_BUFFER)) break; sge++; i++; + if (i >= 32) { + kprintf("%s: SGL walk exceeded frame bounds\n", __func__); + break; + } } }