diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2010-10-09 19:35:33 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2010-10-09 19:35:33 +0000 |
commit | 958e6885331439b7376f5709ed38bd3ee6dd55d7 (patch) | |
tree | e1748ab38ec8a095277c1469566e49c698ae2800 /sys/dev | |
parent | a73cc84893c16144db9cd7eff6df27b2090d0cf8 (diff) |
Make trm(4) work again. Avoid use-after-free of xs fields, don't
discard devices because 2nd INQUIRY (a.k.a. scsi_inquire_vpd())
fails, avoid NULL dereferences, reset bus after a timeout since I
can't see how else to account for an unsupported instruction (e.g.
0x9e, a.k.a. READ_CAPACITY_16).
All found while preparing for iopoolification.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ic/trm.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/sys/dev/ic/trm.c b/sys/dev/ic/trm.c index df00455684b..57de3a0bdce 100644 --- a/sys/dev/ic/trm.c +++ b/sys/dev/ic/trm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trm.c,v 1.22 2010/08/20 17:00:40 jsg Exp $ +/* $OpenBSD: trm.c,v 1.23 2010/10/09 19:35:32 krw Exp $ * ------------------------------------------------------------ * O.S : OpenBSD * File Name : trm.c @@ -328,7 +328,7 @@ trm_scsi_cmd(struct scsi_xfer *xs) bus_space_tag_t iot; struct trm_dcb *pDCB; u_int8_t target, lun; - int i, error, intflag, xferflags; + int i, error, intflag, timeout, xferflags; target = xs->sc_link->target; lun = xs->sc_link->lun; @@ -455,12 +455,17 @@ trm_scsi_cmd(struct scsi_xfer *xs) return; } - while ((--xs->timeout > 0) && ((xs->flags & ITSDONE) == 0)) { + /* Avoid use after free (via scsi_done()) of xs! */ + for (timeout = xs->timeout; timeout > 0; timeout--) { trm_Interrupt(sc); + if (pSRB->xs == NULL) { + splx(intflag); + return; + } DELAY(1000); } - if (xs->timeout == 0) + if (timeout == 0 && pSRB->xs != NULL) trm_timeout(pSRB); splx(intflag); @@ -482,12 +487,12 @@ trm_ResetAllDevParam(struct trm_softc *sc) pEEpromBuf = &trm_eepromBuf[sc->sc_AdapterUnit]; for (target = 0; target < TRM_MAX_TARGETS; target++) { - if (target == sc->sc_AdaptSCSIID) + if (target == sc->sc_AdaptSCSIID || sc->pDCB[target][0] == NULL) continue; if ((sc->pDCB[target][0]->DCBFlag & TRM_QUIRKS_VALID) == 0) quirks = SDEV_NOWIDE | SDEV_NOSYNC | SDEV_NOTAGS; - else + else if (sc->pDCB[target][0]->sc_link != NULL) quirks = sc->pDCB[target][0]->sc_link->quirks; trm_ResetDevParam(sc, sc->pDCB[target][0], quirks); @@ -645,6 +650,7 @@ trm_timeout(void *arg1) sc->sc_device.dv_xname, xs->cmd->opcode); pSRB->SRBFlag |= TRM_SCSI_TIMED_OUT; trm_FinishSRB(sc, pSRB); + trm_reset(sc); trm_StartWaitingSRB(sc); } #ifdef TRM_DEBUG0 @@ -2048,7 +2054,7 @@ trm_FinishSRB(struct trm_softc *sc, struct trm_scsi_req_q *pSRB) if ((xs->flags & SCSI_POLL) != 0) { - if (xs->cmd->opcode == INQUIRY) { + if (xs->cmd->opcode == INQUIRY && pDCB->sc_link == NULL) { ptr = (struct scsi_inquiry_data *) xs->data; |