summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/iscsi_tcp.c13
-rw-r--r--drivers/scsi/libiscsi.c60
2 files changed, 52 insertions, 21 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index dfaf9fa..f2a08f7 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 79bc49f..4bc63c4 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;
OpenPOWER on IntegriCloud