Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iscsi-target: Do not reject non-immediate CmdSNs exceeding MaxCmdSN

This patch changes iscsit_sequence_cmd() logic to no longer reject
non-immediate CmdSNs that exceed MaxCmdSN with a protocol error,
but instead silently ignore them.

This is done to correctly follow RFC-3720 Section 3.2.2.1:

For non-immediate commands, the CmdSN field can take any
value from ExpCmdSN to MaxCmdSN inclusive. The target MUST silently
ignore any non-immediate command outside of this range or non-
immediate duplicates within the range.

Reported-by: Santosh Kulkarni <santosh.kulkarni@calsoftinc.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>

+11 -8
+1
drivers/target/iscsi/iscsi_target_core.h
··· 193 193 CMDSN_NORMAL_OPERATION = 0, 194 194 CMDSN_LOWER_THAN_EXP = 1, 195 195 CMDSN_HIGHER_THAN_EXP = 2, 196 + CMDSN_MAXCMDSN_OVERRUN = 3, 196 197 }; 197 198 198 199 /* Used for iscsi_handle_immediate_data() return values */
+10 -8
drivers/target/iscsi/iscsi_target_util.c
··· 242 242 */ 243 243 if (iscsi_sna_gt(cmdsn, sess->max_cmd_sn)) { 244 244 pr_err("Received CmdSN: 0x%08x is greater than" 245 - " MaxCmdSN: 0x%08x, protocol error.\n", cmdsn, 245 + " MaxCmdSN: 0x%08x, ignoring.\n", cmdsn, 246 246 sess->max_cmd_sn); 247 - ret = CMDSN_ERROR_CANNOT_RECOVER; 247 + ret = CMDSN_MAXCMDSN_OVERRUN; 248 248 249 249 } else if (cmdsn == sess->exp_cmd_sn) { 250 250 sess->exp_cmd_sn++; ··· 303 303 ret = CMDSN_HIGHER_THAN_EXP; 304 304 break; 305 305 case CMDSN_LOWER_THAN_EXP: 306 + case CMDSN_MAXCMDSN_OVERRUN: 307 + default: 306 308 cmd->i_state = ISTATE_REMOVE; 307 309 iscsit_add_cmd_to_immediate_queue(cmd, conn, cmd->i_state); 308 - ret = cmdsn_ret; 309 - break; 310 - default: 311 - reason = ISCSI_REASON_PROTOCOL_ERROR; 312 - reject = true; 313 - ret = cmdsn_ret; 310 + /* 311 + * Existing callers for iscsit_sequence_cmd() will silently 312 + * ignore commands with CMDSN_LOWER_THAN_EXP, so force this 313 + * return for CMDSN_MAXCMDSN_OVERRUN as well.. 314 + */ 315 + ret = CMDSN_LOWER_THAN_EXP; 314 316 break; 315 317 } 316 318 mutex_unlock(&conn->sess->cmdsn_mutex);