Commit 6d8e7e7c authored by Dmitry Bogdanov's avatar Dmitry Bogdanov Committed by Martin K. Petersen

scsi: target: Fix protect handling in WRITE SAME(32)

WRITE SAME(32) command handling reads WRPROTECT at the wrong offset in 1st
byte instead of 10th byte.

Link: https://lore.kernel.org/r/20210702091655.22818-1-d.bogdanov@yadro.com
Fixes: afd73f1b ("target: Perform PROTECT sanity checks for WRITE_SAME")
Signed-off-by: default avatarDmitry Bogdanov <d.bogdanov@yadro.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent e746f345
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include "target_core_alua.h" #include "target_core_alua.h"
static sense_reason_t static sense_reason_t
sbc_check_prot(struct se_device *, struct se_cmd *, unsigned char *, u32, bool); sbc_check_prot(struct se_device *, struct se_cmd *, unsigned char, u32, bool);
static sense_reason_t sbc_execute_unmap(struct se_cmd *cmd); static sense_reason_t sbc_execute_unmap(struct se_cmd *cmd);
static sense_reason_t static sense_reason_t
...@@ -279,14 +279,14 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb) ...@@ -279,14 +279,14 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
} }
static sense_reason_t static sense_reason_t
sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops) sbc_setup_write_same(struct se_cmd *cmd, unsigned char flags, struct sbc_ops *ops)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
sector_t end_lba = dev->transport->get_blocks(dev) + 1; sector_t end_lba = dev->transport->get_blocks(dev) + 1;
unsigned int sectors = sbc_get_write_same_sectors(cmd); unsigned int sectors = sbc_get_write_same_sectors(cmd);
sense_reason_t ret; sense_reason_t ret;
if ((flags[0] & 0x04) || (flags[0] & 0x02)) { if ((flags & 0x04) || (flags & 0x02)) {
pr_err("WRITE_SAME PBDATA and LBDATA" pr_err("WRITE_SAME PBDATA and LBDATA"
" bits not supported for Block Discard" " bits not supported for Block Discard"
" Emulation\n"); " Emulation\n");
...@@ -308,7 +308,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o ...@@ -308,7 +308,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
} }
/* We always have ANC_SUP == 0 so setting ANCHOR is always an error */ /* We always have ANC_SUP == 0 so setting ANCHOR is always an error */
if (flags[0] & 0x10) { if (flags & 0x10) {
pr_warn("WRITE SAME with ANCHOR not supported\n"); pr_warn("WRITE SAME with ANCHOR not supported\n");
return TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
} }
...@@ -316,7 +316,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o ...@@ -316,7 +316,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
* Special case for WRITE_SAME w/ UNMAP=1 that ends up getting * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting
* translated into block discard requests within backend code. * translated into block discard requests within backend code.
*/ */
if (flags[0] & 0x08) { if (flags & 0x08) {
if (!ops->execute_unmap) if (!ops->execute_unmap)
return TCM_UNSUPPORTED_SCSI_OPCODE; return TCM_UNSUPPORTED_SCSI_OPCODE;
...@@ -331,7 +331,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o ...@@ -331,7 +331,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
if (!ops->execute_write_same) if (!ops->execute_write_same)
return TCM_UNSUPPORTED_SCSI_OPCODE; return TCM_UNSUPPORTED_SCSI_OPCODE;
ret = sbc_check_prot(dev, cmd, &cmd->t_task_cdb[0], sectors, true); ret = sbc_check_prot(dev, cmd, flags >> 5, sectors, true);
if (ret) if (ret)
return ret; return ret;
...@@ -717,10 +717,9 @@ sbc_set_prot_op_checks(u8 protect, bool fabric_prot, enum target_prot_type prot_ ...@@ -717,10 +717,9 @@ sbc_set_prot_op_checks(u8 protect, bool fabric_prot, enum target_prot_type prot_
} }
static sense_reason_t static sense_reason_t
sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb, sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char protect,
u32 sectors, bool is_write) u32 sectors, bool is_write)
{ {
u8 protect = cdb[1] >> 5;
int sp_ops = cmd->se_sess->sup_prot_ops; int sp_ops = cmd->se_sess->sup_prot_ops;
int pi_prot_type = dev->dev_attrib.pi_prot_type; int pi_prot_type = dev->dev_attrib.pi_prot_type;
bool fabric_prot = false; bool fabric_prot = false;
...@@ -768,7 +767,7 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb, ...@@ -768,7 +767,7 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
fallthrough; fallthrough;
default: default:
pr_err("Unable to determine pi_prot_type for CDB: 0x%02x " pr_err("Unable to determine pi_prot_type for CDB: 0x%02x "
"PROTECT: 0x%02x\n", cdb[0], protect); "PROTECT: 0x%02x\n", cmd->t_task_cdb[0], protect);
return TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
} }
...@@ -843,7 +842,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -843,7 +842,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
if (sbc_check_dpofua(dev, cmd, cdb)) if (sbc_check_dpofua(dev, cmd, cdb))
return TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
ret = sbc_check_prot(dev, cmd, cdb, sectors, false); ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, false);
if (ret) if (ret)
return ret; return ret;
...@@ -857,7 +856,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -857,7 +856,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
if (sbc_check_dpofua(dev, cmd, cdb)) if (sbc_check_dpofua(dev, cmd, cdb))
return TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
ret = sbc_check_prot(dev, cmd, cdb, sectors, false); ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, false);
if (ret) if (ret)
return ret; return ret;
...@@ -871,7 +870,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -871,7 +870,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
if (sbc_check_dpofua(dev, cmd, cdb)) if (sbc_check_dpofua(dev, cmd, cdb))
return TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
ret = sbc_check_prot(dev, cmd, cdb, sectors, false); ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, false);
if (ret) if (ret)
return ret; return ret;
...@@ -892,7 +891,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -892,7 +891,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
if (sbc_check_dpofua(dev, cmd, cdb)) if (sbc_check_dpofua(dev, cmd, cdb))
return TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
ret = sbc_check_prot(dev, cmd, cdb, sectors, true); ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, true);
if (ret) if (ret)
return ret; return ret;
...@@ -906,7 +905,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -906,7 +905,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
if (sbc_check_dpofua(dev, cmd, cdb)) if (sbc_check_dpofua(dev, cmd, cdb))
return TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
ret = sbc_check_prot(dev, cmd, cdb, sectors, true); ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, true);
if (ret) if (ret)
return ret; return ret;
...@@ -921,7 +920,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -921,7 +920,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
if (sbc_check_dpofua(dev, cmd, cdb)) if (sbc_check_dpofua(dev, cmd, cdb))
return TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
ret = sbc_check_prot(dev, cmd, cdb, sectors, true); ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, true);
if (ret) if (ret)
return ret; return ret;
...@@ -980,7 +979,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -980,7 +979,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
size = sbc_get_size(cmd, 1); size = sbc_get_size(cmd, 1);
cmd->t_task_lba = get_unaligned_be64(&cdb[12]); cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
ret = sbc_setup_write_same(cmd, &cdb[10], ops); ret = sbc_setup_write_same(cmd, cdb[10], ops);
if (ret) if (ret)
return ret; return ret;
break; break;
...@@ -1079,7 +1078,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -1079,7 +1078,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
size = sbc_get_size(cmd, 1); size = sbc_get_size(cmd, 1);
cmd->t_task_lba = get_unaligned_be64(&cdb[2]); cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
ret = sbc_setup_write_same(cmd, &cdb[1], ops); ret = sbc_setup_write_same(cmd, cdb[1], ops);
if (ret) if (ret)
return ret; return ret;
break; break;
...@@ -1097,7 +1096,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -1097,7 +1096,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
* Follow sbcr26 with WRITE_SAME (10) and check for the existence * Follow sbcr26 with WRITE_SAME (10) and check for the existence
* of byte 1 bit 3 UNMAP instead of original reserved field * of byte 1 bit 3 UNMAP instead of original reserved field
*/ */
ret = sbc_setup_write_same(cmd, &cdb[1], ops); ret = sbc_setup_write_same(cmd, cdb[1], ops);
if (ret) if (ret)
return ret; return ret;
break; break;
......
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