[PATCH] scsi: target: iscsi: Fix HeaderDigest to cover AHS data

[email protected]
Newsgroups org.kernel.vger.linux-scsi,org.kernel.vger.linux-kernel,org.kernel.vger.stable,org.kernel.vger.target-devel
Message-ID <[email protected]>
From: Cao Guanghui <[email protected]>

In iscsit_get_rx_pdu(), the HeaderDigest CRC32C is computed over only
the 48-byte basic header (ISCSI_HDR_LEN), excluding any Additional
Header Segments.  However, RFC 3720 Section 10.2.1.2 specifies that
the header digest covers "all the header segments of a PDU, i.e., BHS
and AHS."

The iSCSI initiator (libiscsi) correctly computes the digest over
BHS + AHS (task->hdr_len = 48 + hlength * 4), so any valid PDU with
both HeaderDigest negotiated and AHS present (e.g., SCSI commands with
Extended CDB) would fail CRC verification on the target side and be
falsely rejected.

Track the total header length in a local variable and use it for the
CRC computation so that the digest covers the full header as required
by the RFC.

Fixes: e48354ce078c ("iscsi-target: Add iSCSI fabric support for target v4.1")
Cc: [email protected]
Signed-off-by: Cao Guanghui <[email protected]>
---
 drivers/target/iscsi/iscsi_target.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -4026,6 +4026,6 @@ static void iscsit_get_rx_pdu(struct iscsit_conn *conn)
 {
 	int ret;
 	u8 *buffer, *tmp_buf, opcode;
-	u32 checksum = 0, digest = 0;
+	u32 checksum = 0, digest = 0, header_length;
 	struct iscsi_hdr *hdr;
 	struct kvec iov;
@@ -4053,8 +4053,10 @@ static void iscsit_get_rx_pdu(struct iscsit_conn *conn)
 		}
 
 		hdr = (struct iscsi_hdr *) buffer;
+		header_length = ISCSI_HDR_LEN;
 		if (hdr->hlength) {
 			iov.iov_len = hdr->hlength * 4;
+			header_length = ISCSI_HDR_LEN + iov.iov_len;
 			tmp_buf = krealloc(buffer,
 					  ISCSI_HDR_LEN + iov.iov_len,
 					  GFP_KERNEL);
@@ -4082,5 +4084,5 @@ static void iscsit_get_rx_pdu(struct iscsit_conn *conn)
 			}
 
-			checksum = iscsit_crc_buf(buffer, ISCSI_HDR_LEN, 0,
-						  NULL);
+			checksum = iscsit_crc_buf(buffer, header_length, 0,
+						  NULL);
 			if (digest != checksum) {
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.