[PATCH 1/1] target: fix scatterlist overrun

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Eric Seppanen <eric@xxxxxxxxxxxxxxx>

While playing around with target loopback, I discovered that I could
panic the kernel on older target code with the command:

sg_raw -vv -r 8 /dev/sda 12 00 00 00 24 00

This led to the discovery that transport_memcpy_write_contig() will
happily write off the end of the scatterlist, if the transport size
requested is smaller than the size produced by the CDB.

Patch is against 3.0.7.  I understand that 3.1-rc code has changed
significantly and this patch doesn't apply, but maybe there will be
interest in this for the stable series?

Signed-off-by: Eric Seppanen <eric@xxxxxxxxxxxxxxx>
---
 drivers/target/target_core_transport.c |   15 +++++++++++----
 include/target/target_core_base.h      |    1 +
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 4b9b716..15b454b 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -3700,6 +3700,7 @@ static inline void transport_release_tasks(struct se_cmd *);
 static void transport_memcpy_write_contig(
 	struct se_cmd *cmd,
 	struct scatterlist *sg_d,
+	u32 sgl_count,
 	unsigned char *src)
 {
 	u32 i = 0, length = 0, total_length = cmd->data_length;
@@ -3719,7 +3720,8 @@ static void transport_memcpy_write_contig(
 			return;
 
 		src += length;
-		i++;
+		if (++i >= sgl_count)
+			break;
 	}
 }
 
@@ -3730,7 +3732,8 @@ static void transport_memcpy_write_contig(
 static void transport_memcpy_read_contig(
 	struct se_cmd *cmd,
 	unsigned char *dst,
-	struct scatterlist *sg_s)
+	struct scatterlist *sg_s,
+	u32 sgl_count)
 {
 	u32 i = 0, length = 0, total_length = cmd->data_length;
 	void *src;
@@ -3749,7 +3752,8 @@ static void transport_memcpy_read_contig(
 			return;
 
 		dst += length;
-		i++;
+		if (++i >= sgl_count)
+			break;
 	}
 }
 
@@ -3902,6 +3906,7 @@ static void transport_generic_complete_ok(struct se_cmd *cmd)
 		if (cmd->se_cmd_flags & SCF_PASSTHROUGH_CONTIG_TO_SG)
 			transport_memcpy_write_contig(cmd,
 				 T_TASK(cmd)->t_task_pt_sgl,
+				 T_TASK(cmd)->t_task_sgl_count,
 				 T_TASK(cmd)->t_task_buf);
 
 		CMD_TFO(cmd)->queue_data_in(cmd);
@@ -4222,6 +4227,7 @@ int transport_generic_map_mem_to_cmd(
 		 */
 		cmd->se_cmd_flags |= SCF_PASSTHROUGH_CONTIG_TO_SG;
 		T_TASK(cmd)->t_task_pt_sgl = mem;
+		T_TASK(cmd)->t_task_sgl_count = sg_mem_num;
 	}
 
 	return 0;
@@ -5252,7 +5258,8 @@ static int transport_generic_write_pending(struct se_cmd *cmd)
 	if (cmd->se_cmd_flags & SCF_PASSTHROUGH_CONTIG_TO_SG)
 		transport_memcpy_read_contig(cmd,
 				T_TASK(cmd)->t_task_buf,
-				T_TASK(cmd)->t_task_pt_sgl);
+				T_TASK(cmd)->t_task_pt_sgl,
+				T_TASK(cmd)->t_task_sgl_count);
 	/*
 	 * Clear the se_cmd for WRITE_PENDING status in order to set
 	 * T_TASK(cmd)->t_transport_active=0 so that transport_generic_handle_data
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 561ac99..f65e9d8 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -457,6 +457,7 @@ struct se_transport_task {
 	 * and other HW target mode fabric modules.
 	 */
 	struct scatterlist	*t_task_pt_sgl;
+	u32			t_task_sgl_count;
 	struct list_head	*t_mem_list;
 	/* Used for BIDI READ */
 	struct list_head	*t_mem_bidi_list;
-- 
1.7.4.1
--
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


[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux