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

[SCSI] libfc: fix lun reset failure bugs in fc_fcp_resp handling of FCP_RSP_INFO

In LUN RESET testing involving NetApp targets, it is observed that LUN
RESET is failing. The fc_fcp_resp() is not completing the completion
for the LUN RESET task since fc_fcp_resp assumes that the FCP_RSP_INFO
is 8 bytes with the 4 byte reserved field, where in case of NetApp targets
the FCP_RSP to LUN RESET only has 4 bytes of FCP_RSP_INFO. This leads
fc_fcp_resp to error out w/o completing the task completion, eventually
causing LUN RESET to be escalated to host reset, which is not very nice.

Per FCP-3 r04, clause 9.5.15 and Table 23, the FCP_RSP_INFO field can be either
4 bytes or 8 bytes, with the last 4 bytes as "Reserved (if any)". Therefore it
is valid to have 4 bytes FCP_RSP_INFO like some of the NetApp targets behave.
Fixing this by validating the FCP_RSP_INFO against both the two spec allowed
length.

Reported-by: Frank Zhang <frank_1.zhang@intel.com>
Signed-off-by: Yi Zou <yi.zou@intel.com>
Tested-by: Ross Brattain <ross.b.brattain@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

authored by

Yi Zou and committed by
James Bottomley
3b64b188 31c37a6f

+8 -1
+2 -1
drivers/scsi/libfc/fc_fcp.c
··· 851 851 fc_rp_info = (struct fcp_resp_rsp_info *)(rp_ex + 1); 852 852 if (flags & FCP_RSP_LEN_VAL) { 853 853 respl = ntohl(rp_ex->fr_rsp_len); 854 - if (respl != sizeof(*fc_rp_info)) 854 + if ((respl != FCP_RESP_RSP_INFO_LEN4) && 855 + (respl != FCP_RESP_RSP_INFO_LEN8)) 855 856 goto len_err; 856 857 if (fsp->wait_for_comp) { 857 858 /* Abuse cdb_status for rsp code */
+6
include/scsi/fc/fc_fcp.h
··· 127 127 * 128 128 * All response frames will always contain the fcp_resp template. Some 129 129 * will also include the fcp_resp_len template. 130 + * 131 + * From Table 23, the FCP_RSP_INFO can either be 4 bytes or 8 bytes, both 132 + * are valid length. 130 133 */ 131 134 struct fcp_resp { 132 135 __u8 _fr_resvd[8]; /* reserved */ ··· 158 155 __u8 rsp_code; /* Response Info Code */ 159 156 __u8 _fr_resvd2[4]; /* reserved */ 160 157 }; 158 + 159 + #define FCP_RESP_RSP_INFO_LEN4 4 /* without reserved field */ 160 + #define FCP_RESP_RSP_INFO_LEN8 8 /* with reserved field */ 161 161 162 162 struct fcp_resp_with_ext { 163 163 struct fcp_resp resp;