| From 3c1e2bb35fa6755ce2c3f2fe192b6dacfb276365 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 750a04ed0e93..bf05701f78b3 100644 |
| --- a/drivers/target/target_core_sbc.c |
| +++ b/drivers/target/target_core_sbc.c |
| @@ -38,7 +38,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 |
| @@ -292,14 +292,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"); |
| @@ -321,7 +321,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; |
| } |
| @@ -329,7 +329,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; |
| |
| @@ -344,7 +344,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; |
| |
| @@ -702,10 +702,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; |
| @@ -753,7 +752,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; |
| } |
| |
| @@ -828,7 +827,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; |
| |
| @@ -842,7 +841,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; |
| |
| @@ -856,7 +855,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; |
| |
| @@ -877,7 +876,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; |
| |
| @@ -891,7 +890,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; |
| |
| @@ -965,7 +964,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; |
| @@ -1063,7 +1062,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; |
| @@ -1081,7 +1080,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 |
| |