| From 5568ae84761eef3be8d8ceb2c2e9ac61f864d065 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 2 Jul 2021 12:16:55 +0300 |
| Subject: scsi: target: Fix protect handling in WRITE SAME(32) |
| |
| From: Dmitry Bogdanov <d.bogdanov@yadro.com> |
| |
| [ Upstream commit 6d8e7e7c932162bccd06872362751b0e1d76f5af ] |
| |
| 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: afd73f1b60fc ("target: Perform PROTECT sanity checks for WRITE_SAME") |
| Signed-off-by: Dmitry Bogdanov <d.bogdanov@yadro.com> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/target/target_core_sbc.c | 35 ++++++++++++++++---------------- |
| 1 file changed, 17 insertions(+), 18 deletions(-) |
| |
| diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c |
| index 7b07e557dc8d..6594bb0b9df0 100644 |
| --- a/drivers/target/target_core_sbc.c |
| +++ b/drivers/target/target_core_sbc.c |
| @@ -25,7 +25,7 @@ |
| #include "target_core_alua.h" |
| |
| 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 |
| @@ -279,14 +279,14 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb) |
| } |
| |
| 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; |
| sector_t end_lba = dev->transport->get_blocks(dev) + 1; |
| unsigned int sectors = sbc_get_write_same_sectors(cmd); |
| sense_reason_t ret; |
| |
| - if ((flags[0] & 0x04) || (flags[0] & 0x02)) { |
| + if ((flags & 0x04) || (flags & 0x02)) { |
| pr_err("WRITE_SAME PBDATA and LBDATA" |
| " bits not supported for Block Discard" |
| " Emulation\n"); |
| @@ -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 */ |
| - if (flags[0] & 0x10) { |
| + if (flags & 0x10) { |
| pr_warn("WRITE SAME with ANCHOR not supported\n"); |
| return TCM_INVALID_CDB_FIELD; |
| } |
| @@ -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 |
| * translated into block discard requests within backend code. |
| */ |
| - if (flags[0] & 0x08) { |
| + if (flags & 0x08) { |
| if (!ops->execute_unmap) |
| return TCM_UNSUPPORTED_SCSI_OPCODE; |
| |
| @@ -331,7 +331,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o |
| if (!ops->execute_write_same) |
| 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) |
| return ret; |
| |
| @@ -717,10 +717,9 @@ sbc_set_prot_op_checks(u8 protect, bool fabric_prot, enum target_prot_type prot_ |
| } |
| |
| 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) |
| { |
| - u8 protect = cdb[1] >> 5; |
| int sp_ops = cmd->se_sess->sup_prot_ops; |
| int pi_prot_type = dev->dev_attrib.pi_prot_type; |
| bool fabric_prot = false; |
| @@ -768,7 +767,7 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb, |
| fallthrough; |
| default: |
| 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; |
| } |
| |
| @@ -843,7 +842,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) |
| if (sbc_check_dpofua(dev, cmd, cdb)) |
| 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) |
| return ret; |
| |
| @@ -857,7 +856,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) |
| if (sbc_check_dpofua(dev, cmd, cdb)) |
| 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) |
| return ret; |
| |
| @@ -871,7 +870,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) |
| if (sbc_check_dpofua(dev, cmd, cdb)) |
| 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) |
| return ret; |
| |
| @@ -892,7 +891,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) |
| if (sbc_check_dpofua(dev, cmd, cdb)) |
| 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) |
| return ret; |
| |
| @@ -906,7 +905,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) |
| if (sbc_check_dpofua(dev, cmd, cdb)) |
| 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) |
| return ret; |
| |
| @@ -921,7 +920,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) |
| if (sbc_check_dpofua(dev, cmd, cdb)) |
| 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) |
| return ret; |
| |
| @@ -980,7 +979,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) |
| size = sbc_get_size(cmd, 1); |
| 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) |
| return ret; |
| break; |
| @@ -1079,7 +1078,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) |
| size = sbc_get_size(cmd, 1); |
| 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) |
| return ret; |
| break; |
| @@ -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 |
| * 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) |
| return ret; |
| break; |
| -- |
| 2.30.2 |
| |