aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-08-31 18:09:33 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-09-02 14:37:36 -0400
commitf47f2cf5d4acf929a3aaa6957c3fc4622c358703 (patch)
tree6bf770ac6a789f926728b1881a7eee64a463404f
parentca5186842a6d85e982e3d572ecd407453d0c5116 (diff)
[SCSI] libiscsi: check that command ptr is set before accessing it
If the scsi eh sends a TUR and the session is down we could return SCSI_ML_HOST_BUSY. scsi eh will ignore this and send ask us to abort the command and we blindly accesst the command ptr. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/libiscsi.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 864c6284e83c..12b5c1800740 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -192,6 +192,8 @@ static void iscsi_complete_command(struct iscsi_cmd_task *ctask)
192 192
193 ctask->state = ISCSI_TASK_COMPLETED; 193 ctask->state = ISCSI_TASK_COMPLETED;
194 ctask->sc = NULL; 194 ctask->sc = NULL;
195 /* SCSI eh reuses commands to verify us */
196 sc->SCp.ptr = NULL;
195 list_del_init(&ctask->running); 197 list_del_init(&ctask->running);
196 __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); 198 __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
197 sc->scsi_done(sc); 199 sc->scsi_done(sc);
@@ -737,6 +739,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
737 739
738 sc->scsi_done = done; 740 sc->scsi_done = done;
739 sc->result = 0; 741 sc->result = 0;
742 sc->SCp.ptr = NULL;
740 743
741 host = sc->device->host; 744 host = sc->device->host;
742 session = iscsi_hostdata(host->hostdata); 745 session = iscsi_hostdata(host->hostdata);
@@ -801,9 +804,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
801 804
802 list_add_tail(&ctask->running, &conn->xmitqueue); 805 list_add_tail(&ctask->running, &conn->xmitqueue);
803 debug_scsi( 806 debug_scsi(
804 "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n", 807 "ctask enq [%s cid %d sc %p cdb 0x%x itt 0x%x len %d cmdsn %d "
808 "win %d]\n",
805 sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", 809 sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
806 conn->id, (long)sc, ctask->itt, sc->request_bufflen, 810 conn->id, sc, sc->cmnd[0], ctask->itt, sc->request_bufflen,
807 session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); 811 session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
808 spin_unlock(&session->lock); 812 spin_unlock(&session->lock);
809 813
@@ -1134,11 +1138,24 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
1134 1138
1135int iscsi_eh_abort(struct scsi_cmnd *sc) 1139int iscsi_eh_abort(struct scsi_cmnd *sc)
1136{ 1140{
1137 struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; 1141 struct iscsi_cmd_task *ctask;
1138 struct iscsi_conn *conn = ctask->conn; 1142 struct iscsi_conn *conn;
1139 struct iscsi_session *session = conn->session; 1143 struct iscsi_session *session;
1140 int rc; 1144 int rc;
1141 1145
1146 /*
1147 * if session was ISCSI_STATE_IN_RECOVERY then we may not have
1148 * got the command.
1149 */
1150 if (!sc->SCp.ptr) {
1151 debug_scsi("sc never reached iscsi layer or it completed.\n");
1152 return SUCCESS;
1153 }
1154
1155 ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
1156 conn = ctask->conn;
1157 session = conn->session;
1158
1142 conn->eh_abort_cnt++; 1159 conn->eh_abort_cnt++;
1143 debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); 1160 debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
1144 1161