aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-11-15 22:13:24 -0800
committerNicholas Bellinger <nab@linux-iscsi.org>2011-12-06 06:00:53 +0000
commitfef58a6096770ed6ab49103a430cc755254a74d9 (patch)
treee59f7c7074c32e604a9b1a9f15550c0249e12546
parent6fd126ffebef3897d8fca98644a9fd1cc5c7a5e3 (diff)
downloadlinux-fef58a6096770ed6ab49103a430cc755254a74d9.tar.gz
target: Reject SCSI data overflow for fabrics using transport_generic_map_mem_to_cmd
This patch changes transport_generic_map_mem_to_cmd() to reject SCSI data overflow and to send exception status with CHECK_CONDITION + TCM_INVALID_CDB_FIELD for fabrics that are passing a pre-populated struct scatterlist (eg: tcm_loop and iscsi-target) being mapped into se_cmd->t_data_sg and se_cmd->t_data_nents. This addresses an OOPs where transport_allocate_data_tasks() would walk the incorrect post OVERFLOW cmd->data_length value beyond the end of the passed scatterlist. Cc: Christoph Hellwig <hch@lst.de> Cc: Andy Grover <agrover@redhat.com> Cc: stable@kernel.org Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/target/target_core_transport.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 8f29f472c50bd1..0bdb6badbf9968 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -3411,6 +3411,18 @@ int transport_generic_map_mem_to_cmd(
if ((cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) ||
(cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB)) {
+ /*
+ * Reject SCSI data overflow with map_mem_to_cmd() as incoming
+ * scatterlists already have been set to follow what the fabric
+ * passes for the original expected data transfer length.
+ */
+ if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
+ pr_warn("Rejecting SCSI DATA overflow for fabric using"
+ " SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n");
+ cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+ cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+ return -EINVAL;
+ }
cmd->t_data_sg = sgl;
cmd->t_data_nents = sgl_count;