target_core_rd: break out unterminated loop during copy
authorHannes Reinecke <hare@suse.de>
Wed, 6 Feb 2013 13:42:28 +0000 (14:42 +0100)
committerNicholas Bellinger <nab@linux-iscsi.org>
Wed, 13 Feb 2013 19:54:29 +0000 (11:54 -0800)
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>
drivers/target/target_core_rd.c

index b0fff52c990e517722f88085ef04ef61432777e6..e0b3c379aa148c75d4364dccbb47720c0db1b731 100644 (file)
@@ -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;