diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 13 | ||||
-rw-r--r-- | drivers/scsi/libiscsi.c | 60 |
2 files changed, 52 insertions, 21 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index dfaf9fa57340..f2a08f7ed902 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -740,7 +740,6 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) struct iscsi_session *session = conn->session; struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct iscsi_cmd_task *ctask; - uint32_t itt; /* verify PDU length */ tcp_conn->in.datalen = ntoh24(hdr->dlength); @@ -758,7 +757,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) opcode = hdr->opcode & ISCSI_OPCODE_MASK; /* verify itt (itt encoding: age+cid+itt) */ - rc = iscsi_verify_itt(conn, hdr, &itt); + rc = iscsi_verify_itt(conn, hdr->itt); if (rc) return rc; @@ -767,7 +766,10 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) switch(opcode) { case ISCSI_OP_SCSI_DATA_IN: - ctask = session->cmds[itt]; + ctask = iscsi_itt_to_ctask(conn, hdr->itt); + if (!ctask) + return ISCSI_ERR_BAD_ITT; + spin_lock(&conn->session->lock); rc = iscsi_data_rsp(conn, ctask); spin_unlock(&conn->session->lock); @@ -810,7 +812,10 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) rc = iscsi_complete_pdu(conn, hdr, NULL, 0); break; case ISCSI_OP_R2T: - ctask = session->cmds[itt]; + ctask = iscsi_itt_to_ctask(conn, hdr->itt); + if (!ctask) + return ISCSI_ERR_BAD_ITT; + if (ahslen) rc = ISCSI_ERR_AHSLEN; else if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) { diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 79bc49fd7f12..4bc63c4b3c10 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -640,6 +640,10 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, uint32_t itt; conn->last_recv = jiffies; + rc = iscsi_verify_itt(conn, hdr->itt); + if (rc) + return rc; + if (hdr->itt != RESERVED_ITT) itt = get_itt(hdr->itt); else @@ -776,27 +780,22 @@ int iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, } EXPORT_SYMBOL_GPL(iscsi_complete_pdu); -/* verify itt (itt encoding: age+cid+itt) */ -int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr, - uint32_t *ret_itt) +int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt) { struct iscsi_session *session = conn->session; struct iscsi_cmd_task *ctask; - uint32_t itt; - if (hdr->itt != RESERVED_ITT) { - if (((__force u32)hdr->itt & ISCSI_AGE_MASK) != - (session->age << ISCSI_AGE_SHIFT)) { - iscsi_conn_printk(KERN_ERR, conn, - "received itt %x expected session " - "age (%x)\n", (__force u32)hdr->itt, - session->age & ISCSI_AGE_MASK); - return ISCSI_ERR_BAD_ITT; - } + if (itt == RESERVED_ITT) + return 0; - itt = get_itt(hdr->itt); - } else - itt = ~0U; + if (((__force u32)itt & ISCSI_AGE_MASK) != + (session->age << ISCSI_AGE_SHIFT)) { + iscsi_conn_printk(KERN_ERR, conn, + "received itt %x expected session age (%x)\n", + (__force u32)itt, + session->age & ISCSI_AGE_MASK); + return ISCSI_ERR_BAD_ITT; + } if (itt < session->cmds_max) { ctask = session->cmds[itt]; @@ -817,11 +816,38 @@ int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr, } } - *ret_itt = itt; return 0; } EXPORT_SYMBOL_GPL(iscsi_verify_itt); +struct iscsi_cmd_task * +iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt) +{ + struct iscsi_session *session = conn->session; + struct iscsi_cmd_task *ctask; + uint32_t i; + + if (iscsi_verify_itt(conn, itt)) + return NULL; + + if (itt == RESERVED_ITT) + return NULL; + + i = get_itt(itt); + if (i >= session->cmds_max) + return NULL; + + ctask = session->cmds[i]; + if (!ctask->sc) + return NULL; + + if (ctask->sc->SCp.phase != session->age) + return NULL; + + return ctask; +} +EXPORT_SYMBOL_GPL(iscsi_itt_to_ctask); + void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) { struct iscsi_session *session = conn->session; |