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