Commit f6cfba1d authored by Mike Christie's avatar Mike Christie Committed by James Bottomley

[SCSI] iscsi: data digest calculation fix

From Wang Zhenyu:

data digest fix (the bug caused data corruption w/Wasabi StorageBuilder target)
Signed-off-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarAlex Aizman <itn780@yahoo.com>
Signed-off-by: default avatarDmitry Yusupov <dmitry_yus@yahoo.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 733bb6a7
...@@ -903,11 +903,20 @@ partial_sg_digest_update(struct iscsi_conn *conn, struct scatterlist *sg, ...@@ -903,11 +903,20 @@ partial_sg_digest_update(struct iscsi_conn *conn, struct scatterlist *sg,
crypto_digest_update(conn->data_rx_tfm, &temp, 1); crypto_digest_update(conn->data_rx_tfm, &temp, 1);
} }
static void
iscsi_recv_digest_update(struct iscsi_conn *conn, char* buf, int len)
{
struct scatterlist tmp;
sg_init_one(&tmp, buf, len);
crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
}
static int iscsi_scsi_data_in(struct iscsi_conn *conn) static int iscsi_scsi_data_in(struct iscsi_conn *conn)
{ {
struct iscsi_cmd_task *ctask = conn->in.ctask; struct iscsi_cmd_task *ctask = conn->in.ctask;
struct scsi_cmnd *sc = ctask->sc; struct scsi_cmnd *sc = ctask->sc;
struct scatterlist tmp, *sg; struct scatterlist *sg;
int i, offset, rc = 0; int i, offset, rc = 0;
BUG_ON((void*)ctask != sc->SCp.ptr); BUG_ON((void*)ctask != sc->SCp.ptr);
...@@ -921,10 +930,8 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) ...@@ -921,10 +930,8 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
sc->request_bufflen, ctask->data_offset); sc->request_bufflen, ctask->data_offset);
if (rc == -EAGAIN) if (rc == -EAGAIN)
return rc; return rc;
if (conn->datadgst_en) { if (conn->datadgst_en)
sg_init_one(&tmp, sc->request_buffer, i); iscsi_recv_digest_update(conn, sc->request_buffer, i);
crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
}
rc = 0; rc = 0;
goto done; goto done;
} }
...@@ -1018,6 +1025,9 @@ iscsi_data_recv(struct iscsi_conn *conn) ...@@ -1018,6 +1025,9 @@ iscsi_data_recv(struct iscsi_conn *conn)
conn->in.hdr = &conn->hdr; conn->in.hdr = &conn->hdr;
conn->senselen = (conn->data[0] << 8) | conn->data[1]; conn->senselen = (conn->data[0] << 8) | conn->data[1];
rc = iscsi_cmd_rsp(conn, conn->in.ctask); rc = iscsi_cmd_rsp(conn, conn->in.ctask);
if (!rc && conn->datadgst_en)
iscsi_recv_digest_update(conn, conn->data,
conn->in.datalen);
} }
break; break;
case ISCSI_OP_TEXT_RSP: case ISCSI_OP_TEXT_RSP:
...@@ -1042,6 +1052,11 @@ iscsi_data_recv(struct iscsi_conn *conn) ...@@ -1042,6 +1052,11 @@ iscsi_data_recv(struct iscsi_conn *conn)
rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr, rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr,
conn->data, conn->in.datalen); conn->data, conn->in.datalen);
if (!rc && conn->datadgst_en &&
conn->in.opcode != ISCSI_OP_LOGIN_RSP)
iscsi_recv_digest_update(conn, conn->data,
conn->in.datalen);
if (mtask && conn->login_mtask != mtask) { if (mtask && conn->login_mtask != mtask) {
spin_lock(&session->lock); spin_lock(&session->lock);
__kfifo_put(session->mgmtpool.queue, (void*)&mtask, __kfifo_put(session->mgmtpool.queue, (void*)&mtask,
...@@ -1050,6 +1065,8 @@ iscsi_data_recv(struct iscsi_conn *conn) ...@@ -1050,6 +1065,8 @@ iscsi_data_recv(struct iscsi_conn *conn)
} }
} }
break; break;
case ISCSI_OP_ASYNC_EVENT:
case ISCSI_OP_REJECT:
default: default:
BUG_ON(1); BUG_ON(1);
} }
...@@ -1112,7 +1129,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, ...@@ -1112,7 +1129,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
rc = iscsi_hdr_recv(conn); rc = iscsi_hdr_recv(conn);
if (!rc && conn->in.datalen) { if (!rc && conn->in.datalen) {
if (conn->datadgst_en && if (conn->datadgst_en &&
conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) { conn->in.opcode != ISCSI_OP_LOGIN_RSP) {
BUG_ON(!conn->data_rx_tfm); BUG_ON(!conn->data_rx_tfm);
crypto_digest_init(conn->data_rx_tfm); crypto_digest_init(conn->data_rx_tfm);
} }
...@@ -1124,10 +1141,9 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, ...@@ -1124,10 +1141,9 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
} }
if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) { if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
uint32_t recv_digest;
debug_tcp("extra data_recv offset %d copy %d\n", debug_tcp("extra data_recv offset %d copy %d\n",
conn->in.offset, conn->in.copy); conn->in.offset, conn->in.copy);
if (conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
uint32_t recv_digest;
skb_copy_bits(conn->in.skb, conn->in.offset, skb_copy_bits(conn->in.skb, conn->in.offset,
&recv_digest, 4); &recv_digest, 4);
conn->in.offset += 4; conn->in.offset += 4;
...@@ -1145,7 +1161,6 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, ...@@ -1145,7 +1161,6 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
conn->in_progress = IN_PROGRESS_WAIT_HEADER; conn->in_progress = IN_PROGRESS_WAIT_HEADER;
} }
} }
}
if (conn->in_progress == IN_PROGRESS_DATA_RECV && conn->in.copy) { if (conn->in_progress == IN_PROGRESS_DATA_RECV && conn->in.copy) {
...@@ -1165,7 +1180,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, ...@@ -1165,7 +1180,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
conn->in.copy -= conn->in.padding; conn->in.copy -= conn->in.padding;
conn->in.offset += conn->in.padding; conn->in.offset += conn->in.padding;
if (conn->datadgst_en && if (conn->datadgst_en &&
conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) { conn->in.opcode != ISCSI_OP_LOGIN_RSP) {
if (conn->in.padding) { if (conn->in.padding) {
debug_tcp("padding -> %d\n", conn->in.padding); debug_tcp("padding -> %d\n", conn->in.padding);
memset(pad, 0, conn->in.padding); memset(pad, 0, conn->in.padding);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment