diff options
| author | Hannes Reinecke <hare@suse.de> | 2013-02-06 08:42:28 -0500 |
|---|---|---|
| committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-02-13 14:54:29 -0500 |
| commit | bbf344e54ed9a76e344d08feedc70ab2c5a8a64c (patch) | |
| tree | e3740b8ca23f80f042b566b97f67bb8f634f0f5e | |
| parent | 1b7f390eb3bfc197c979c5478eadbc2a90f07667 (diff) | |
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>
| -rw-r--r-- | drivers/target/target_core_rd.c | 12 |
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) | |||
| 316 | void *rd_addr; | 316 | void *rd_addr; |
| 317 | 317 | ||
| 318 | sg_miter_next(&m); | 318 | sg_miter_next(&m); |
| 319 | if (!(u32)m.length) { | ||
| 320 | pr_debug("RD[%u]: invalid sgl %p len %zu\n", | ||
| 321 | dev->rd_dev_id, m.addr, m.length); | ||
| 322 | sg_miter_stop(&m); | ||
| 323 | return TCM_INCORRECT_AMOUNT_OF_DATA; | ||
| 324 | } | ||
| 319 | len = min((u32)m.length, src_len); | 325 | len = min((u32)m.length, src_len); |
| 326 | if (len > rd_size) { | ||
| 327 | pr_debug("RD[%u]: size underrun page %d offset %d " | ||
| 328 | "size %d\n", dev->rd_dev_id, | ||
| 329 | rd_page, rd_offset, rd_size); | ||
| 330 | len = rd_size; | ||
| 331 | } | ||
| 320 | m.consumed = len; | 332 | m.consumed = len; |
| 321 | 333 | ||
| 322 | rd_addr = sg_virt(rd_sg) + rd_offset; | 334 | rd_addr = sg_virt(rd_sg) + rd_offset; |
