summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2010-10-09 19:35:33 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2010-10-09 19:35:33 +0000
commit958e6885331439b7376f5709ed38bd3ee6dd55d7 (patch)
treee1748ab38ec8a095277c1469566e49c698ae2800 /sys/dev
parenta73cc84893c16144db9cd7eff6df27b2090d0cf8 (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.c20
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;