summaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2013-02-06 14:42:28 +0100
committerNicholas Bellinger <nab@linux-iscsi.org>2013-02-13 20:54:29 +0100
commitbbf344e54ed9a76e344d08feedc70ab2c5a8a64c (patch)
treee3740b8ca23f80f042b566b97f67bb8f634f0f5e /drivers/target
parenttcm_vhost: Multi-queue support (diff)
downloadlinux-bbf344e54ed9a76e344d08feedc70ab2c5a8a64c.tar.xz
linux-bbf344e54ed9a76e344d08feedc70ab2c5a8a64c.zip
target_core_rd: break out unterminated loop during copy
The loop in rd_execute_rw() will never terminate if the sg element has a zero size. Or it'll spill over into outer space if the sg element is larger than the available space. So we need to add some safety catches here. Cc: Nic Bellinger <nab@risingtidesystems.com> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/target_core_rd.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c
index b0fff52c990e..e0b3c379aa14 100644
--- a/drivers/target/target_core_rd.c
+++ b/drivers/target/target_core_rd.c
@@ -316,7 +316,19 @@ rd_execute_rw(struct se_cmd *cmd)
void *rd_addr;
sg_miter_next(&m);
+ if (!(u32)m.length) {
+ pr_debug("RD[%u]: invalid sgl %p len %zu\n",
+ dev->rd_dev_id, m.addr, m.length);
+ sg_miter_stop(&m);
+ return TCM_INCORRECT_AMOUNT_OF_DATA;
+ }
len = min((u32)m.length, src_len);
+ if (len > rd_size) {
+ pr_debug("RD[%u]: size underrun page %d offset %d "
+ "size %d\n", dev->rd_dev_id,
+ rd_page, rd_offset, rd_size);
+ len = rd_size;
+ }
m.consumed = len;
rd_addr = sg_virt(rd_sg) + rd_offset;