⬢ DragonFlyBSD Kernel Audit
DF-3672 / fix.diff
← back to finding ↓ download raw
--- 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;