A similar check is performed at the end of sbc_parse_cdb() and is now enforced if the SYNCHRONIZE CACHE command has a non zero logical block address or number of blocks. Signed-off-by: Christophe Vu-Brugier <cvubrugier@xxxxxxxx> --- I think that the check performed in sbc_check_valid_sectors() was wrong because it used cmd->data_length instead of using the number of sectors from the CDB. drivers/target/target_core_sbc.c | 47 ++++++++-------------------------------- 1 file changed, 9 insertions(+), 38 deletions(-) diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index e022959..aaec147 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -176,24 +176,6 @@ static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors) return cmd->se_dev->dev_attrib.block_size * sectors; } -static int sbc_check_valid_sectors(struct se_cmd *cmd) -{ - struct se_device *dev = cmd->se_dev; - unsigned long long end_lba; - u32 sectors; - - sectors = cmd->data_length / dev->dev_attrib.block_size; - end_lba = dev->transport->get_blocks(dev) + 1; - - if (cmd->t_task_lba + sectors > end_lba) { - pr_err("target: lba %llu, sectors %u exceeds end lba %llu\n", - cmd->t_task_lba, sectors, end_lba); - return -EINVAL; - } - - return 0; -} - static inline u32 transport_get_sectors_6(unsigned char *cdb) { /* @@ -680,6 +662,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) unsigned int size; u32 sectors = 0; sense_reason_t ret; + bool lba_check = false; switch (cdb[0]) { case READ_6: @@ -877,15 +860,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) break; case SYNCHRONIZE_CACHE: case SYNCHRONIZE_CACHE_16: - if (!ops->execute_sync_cache) { - size = 0; - cmd->execute_cmd = sbc_emulate_noop; - break; - } - - /* - * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE - */ if (cdb[0] == SYNCHRONIZE_CACHE) { sectors = transport_get_sectors_10(cdb); cmd->t_task_lba = transport_lba_32(cdb); @@ -893,18 +867,15 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) sectors = transport_get_sectors_16(cdb); cmd->t_task_lba = transport_lba_64(cdb); } - size = sbc_get_size(cmd, sectors); - - /* - * Check to ensure that LBA + Range does not exceed past end of - * device for IBLOCK and FILEIO ->do_sync_cache() backend calls - */ - if (cmd->t_task_lba || sectors) { - if (sbc_check_valid_sectors(cmd) < 0) - return TCM_ADDRESS_OUT_OF_RANGE; + if (cmd->t_task_lba || sectors) + lba_check = true; + if (ops->execute_sync_cache) + cmd->execute_cmd = ops->execute_sync_cache; + else { + size = 0; + cmd->execute_cmd = sbc_emulate_noop; } - cmd->execute_cmd = ops->execute_sync_cache; break; case UNMAP: if (!ops->execute_unmap) @@ -971,7 +942,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->execute_cmd) return TCM_UNSUPPORTED_SCSI_OPCODE; - if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { + if ((cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) || lba_check) { unsigned long long end_lba; if (sectors > dev->dev_attrib.fabric_max_sectors) { -- 2.0.0.rc2 -- To unsubscribe from this list: send the line "unsubscribe target-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html