git: 412a8b92d9c0 - stable/13 - Further refine the ExpDataSN checks for SCSI Response PDUs.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Tue, 23 Nov 2021 23:12:53 UTC
The branch stable/13 has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=412a8b92d9c0490ba700f5ea4f676a16778643bd

commit 412a8b92d9c0490ba700f5ea4f676a16778643bd
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2021-10-26 21:50:05 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2021-11-23 23:11:44 +0000

    Further refine the ExpDataSN checks for SCSI Response PDUs.
    
    According to 11.4.8 in RFC 7143, ExpDataSN MUST be 0 if the response
    code is not Command Completed, but we were requiring it to always be
    the count of DataIn PDUs regardless of the response code.
    
    In addition, at least one target (OCI Oracle iSCSI block device)
    returns an ExpDataSN of 0 when returning a valid completion with an
    error status (Check Condition) in response to a SCSI Inquiry.  As a
    workaround for this target, only warn without resetting the connection
    for a 0 ExpDataSN for responses with a non-zero error status.
    
    PR:             259152
    Reported by:    dch
    Reviewed by:    dch, mav, emaste
    Fixes:          4f0f5bf99591 iscsi: Validate DataSN values in Data-In PDUs in the initiator.
    Sponsored by:   Chelsio Communications
    Differential Revision:  https://reviews.freebsd.org/D32650
    
    (cherry picked from commit cdbc4a074bec094dc7f1dfde0773a9417d118ffa)
---
 sys/dev/iscsi/iscsi.c | 40 ++++++++++++++++++++++++++++++++--------
 1 file changed, 32 insertions(+), 8 deletions(-)

diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c
index 093ba51d265e..cc860e3f68a8 100644
--- a/sys/dev/iscsi/iscsi.c
+++ b/sys/dev/iscsi/iscsi.c
@@ -892,15 +892,39 @@ iscsi_pdu_handle_scsi_response(struct icl_pdu *response)
 	}
 
 	ccb = io->io_ccb;
-	if (ntohl(bhssr->bhssr_expdatasn) != io->io_datasn) {
-		ISCSI_SESSION_WARN(is,
-		    "ExpDataSN mismatch in SCSI Response (%u vs %u)",
-		    ntohl(bhssr->bhssr_expdatasn), io->io_datasn);
-		icl_pdu_free(response);
-		iscsi_session_reconnect(is);
-		ISCSI_SESSION_UNLOCK(is);
-		return;
+	if (bhssr->bhssr_response == BHSSR_RESPONSE_COMMAND_COMPLETED) {
+		if (ntohl(bhssr->bhssr_expdatasn) != io->io_datasn) {
+			ISCSI_SESSION_WARN(is,
+			    "ExpDataSN mismatch in SCSI Response (%u vs %u)",
+			    ntohl(bhssr->bhssr_expdatasn), io->io_datasn);
+
+			/*
+			 * XXX: Permit an ExpDataSN of zero for errors.
+			 *
+			 * This doesn't conform to RFC 7143, but some
+			 * targets seem to do this.
+			 */
+			if (bhssr->bhssr_status != 0 &&
+			    bhssr->bhssr_expdatasn == htonl(0))
+				goto skip_expdatasn;
+
+			icl_pdu_free(response);
+			iscsi_session_reconnect(is);
+			ISCSI_SESSION_UNLOCK(is);
+			return;
+		}
+	} else {
+		if (bhssr->bhssr_expdatasn != htonl(0)) {
+			ISCSI_SESSION_WARN(is,
+			    "ExpDataSN mismatch in SCSI Response (%u vs 0)",
+			    ntohl(bhssr->bhssr_expdatasn));
+			icl_pdu_free(response);
+			iscsi_session_reconnect(is);
+			ISCSI_SESSION_UNLOCK(is);
+			return;
+		}
 	}
+skip_expdatasn:
 
 	/*
 	 * With iSER, after getting good response we can be sure