--- a/sys/dev/disk/mpt/mpt.h +++ b/sys/dev/disk/mpt/mpt.h @@ -354,11 +354,19 @@ */ #define MPT_MAKE_TAGID(mpt, req, ioindex) \ ((ioindex << 18) | (((mpt->sequence++) & 0x3f) << 12) | (req->index & 0xfff)) -#ifdef INVARIANTS -#define MPT_TAG_2_REQ(a, b) mpt_tag_2_req(a, (uint32_t) b) -#else -#define MPT_TAG_2_REQ(mpt, tag) mpt->tgt_cmd_ptrs[tag >> 18] -#endif +/* + * The tag lookup is reachable with a user-supplied tag_id (XPT_CONT_TARGET_IO + * via pass(4)); the bounds check must not be DIAGNOSTIC-only. Returns NULL + * for out-of-range tags; callers must treat NULL as "bad tag" and complete + * the CCB with CAM_REQ_CMP_ERR / CAM_TAG_NONE. + */ +#define MPT_TAG_2_REQ(a, b) mpt_tag_2_req(a, (uint32_t)(b)) #define MPT_TGT_STATE(mpt, req) ((mpt_tgt_state_t *) \ (&((uint8_t *)req->req_vbuf)[MPT_RQSL(mpt) - sizeof (mpt_tgt_state_t)])) @@ -951,7 +959,6 @@ return (16); } } -#ifdef INVARIANTS static __inline request_t * mpt_tag_2_req(struct mpt_softc *, uint32_t); static __inline request_t * mpt_tag_2_req(struct mpt_softc *mpt, uint32_t tag) @@ -955,6 +962,7 @@ mpt_tag_2_req(struct mpt_softc *mpt, uint32_t tag) { uint16_t rtg = (tag >> 18); - KASSERT(rtg < mpt->tgt_cmds_allocated, ("bad tag %d", tag)); - KASSERT(mpt->tgt_cmd_ptrs, ("no cmd backpointer array")); - KASSERT(mpt->tgt_cmd_ptrs[rtg], ("no cmd backpointer")); + if (rtg >= mpt->tgt_cmds_allocated || mpt->tgt_cmd_ptrs == NULL || + mpt->tgt_cmd_ptrs[rtg] == NULL) + return (NULL); return (mpt->tgt_cmd_ptrs[rtg]); } -#endif static __inline int mpt_req_on_free_list(struct mpt_softc *, request_t *); --- a/sys/dev/disk/mpt/mpt_cam.c +++ b/sys/dev/disk/mpt/mpt_cam.c @@ -4352,9 +4352,18 @@ mpt_target_start_io(struct mpt_softc *mpt, union ccb *ccb) { struct ccb_scsiio *csio = &ccb->csio; request_t *cmd_req = MPT_TAG_2_REQ(mpt, csio->tag_id); - mpt_tgt_state_t *tgt = MPT_TGT_STATE(mpt, cmd_req); + mpt_tgt_state_t *tgt; + + if (cmd_req == NULL) { + mpt_prt(mpt, "ccb %p tag 0x%08x has no target command\n", + ccb, csio->tag_id); + mpt_set_ccb_status(ccb, CAM_REQ_CMP_ERR); + xpt_done(ccb); + return; + } + tgt = MPT_TGT_STATE(mpt, cmd_req); switch (tgt->state) { @@ -1339,6 +1348,10 @@ bad: } if (hdrp->Function == MPI_FUNCTION_TARGET_ASSIST) { request_t *cmd_req = MPT_TAG_2_REQ(mpt, ccb->csio.tag_id); + if (cmd_req == NULL) + goto no_tgt_state; MPT_TGT_STATE(mpt, cmd_req)->state = TGT_STATE_IN_CAM; MPT_TGT_STATE(mpt, cmd_req)->ccb = NULL; MPT_TGT_STATE(mpt, cmd_req)->req = NULL; @@ -1615,6 +1628,10 @@ out: if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { if (hdrp->Function == MPI_FUNCTION_TARGET_ASSIST) { request_t *cmd_req = MPT_TAG_2_REQ(mpt, ccb->csio.tag_id); + if (cmd_req == NULL) + goto no_tgt_state; MPT_TGT_STATE(mpt, cmd_req)->state = TGT_STATE_IN_CAM; MPT_TGT_STATE(mpt, cmd_req)->ccb = NULL; MPT_TGT_STATE(mpt, cmd_req)->req = NULL; @@ -1742,6 +1759,10 @@ bad: } if (hdrp->Function == MPI_FUNCTION_TARGET_ASSIST) { request_t *cmd_req = MPT_TAG_2_REQ(mpt, ccb->csio.tag_id); + if (cmd_req == NULL) + goto no_tgt_state; MPT_TGT_STATE(mpt, cmd_req)->state = TGT_STATE_IN_CAM; MPT_TGT_STATE(mpt, cmd_req)->ccb = NULL; MPT_TGT_STATE(mpt, cmd_req)->req = NULL; @@ -2002,6 +2023,10 @@ out: if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { if (hdrp->Function == MPI_FUNCTION_TARGET_ASSIST) { request_t *cmd_req = MPT_TAG_2_REQ(mpt, ccb->csio.tag_id); + if (cmd_req == NULL) + goto no_tgt_state; MPT_TGT_STATE(mpt, cmd_req)->state = TGT_STATE_IN_CAM; MPT_TGT_STATE(mpt, cmd_req)->ccb = NULL; MPT_TGT_STATE(mpt, cmd_req)->req = NULL;