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

[SCSI] iscsi_tcp: fix partial digest recv

When a digest is spread across two network buffers, we currently
ignore this and try to check the digest with the partial buffer.
Or course this fails. This patch has use iscsi_tcp_copy to
copy the whole digest before testing it.
Signed-off-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent db98ccde
...@@ -648,10 +648,9 @@ iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask, ...@@ -648,10 +648,9 @@ iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask,
* byte counters. * byte counters.
**/ **/
static inline int static inline int
iscsi_tcp_copy(struct iscsi_conn *conn) iscsi_tcp_copy(struct iscsi_conn *conn, int buf_size)
{ {
struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
int buf_size = tcp_conn->in.datalen;
int buf_left = buf_size - tcp_conn->data_copied; int buf_left = buf_size - tcp_conn->data_copied;
int size = min(tcp_conn->in.copy, buf_left); int size = min(tcp_conn->in.copy, buf_left);
int rc; int rc;
...@@ -812,7 +811,7 @@ iscsi_data_recv(struct iscsi_conn *conn) ...@@ -812,7 +811,7 @@ iscsi_data_recv(struct iscsi_conn *conn)
* Collect data segment to the connection's data * Collect data segment to the connection's data
* placeholder * placeholder
*/ */
if (iscsi_tcp_copy(conn)) { if (iscsi_tcp_copy(conn, tcp_conn->in.datalen)) {
rc = -EAGAIN; rc = -EAGAIN;
goto exit; goto exit;
} }
...@@ -899,10 +898,15 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, ...@@ -899,10 +898,15 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
debug_tcp("extra data_recv offset %d copy %d\n", debug_tcp("extra data_recv offset %d copy %d\n",
tcp_conn->in.offset, tcp_conn->in.copy); tcp_conn->in.offset, tcp_conn->in.copy);
skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, rc = iscsi_tcp_copy(conn, sizeof(uint32_t));
&recv_digest, 4); if (rc) {
tcp_conn->in.offset += 4; if (rc == -EAGAIN)
tcp_conn->in.copy -= 4; goto again;
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
return 0;
}
memcpy(&recv_digest, conn->data, sizeof(uint32_t));
if (recv_digest != tcp_conn->in.datadgst) { if (recv_digest != tcp_conn->in.datadgst) {
debug_tcp("iscsi_tcp: data digest error!" debug_tcp("iscsi_tcp: data digest error!"
"0x%x != 0x%x\n", recv_digest, "0x%x != 0x%x\n", recv_digest,
...@@ -942,9 +946,10 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, ...@@ -942,9 +946,10 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
&sg, 1); &sg, 1);
} }
crypto_digest_final(tcp_conn->rx_tfm, crypto_digest_final(tcp_conn->rx_tfm,
(u8 *) & tcp_conn->in.datadgst); (u8 *) &tcp_conn->in.datadgst);
debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst); debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV; tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
tcp_conn->data_copied = 0;
} else } else
tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
} }
......
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