From: Greg Kroah-Hartman Date: Mon, 13 Aug 2012 18:33:19 +0000 (-0700) Subject: 3.4-stable patches X-Git-Tag: v3.5.2~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f56797b2a5e81fb1d3ff6ae10fe425ab51e61fd9;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: target-add-range-checking-to-unmap-emulation.patch target-check-number-of-unmap-descriptors-against-our-limit.patch target-fix-possible-integer-underflow-in-unmap-emulation.patch target-fix-reading-of-data-length-fields-for-unmap-commands.patch --- diff --git a/queue-3.4/series b/queue-3.4/series index a9ec21ac537..f06f80ae6f7 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -48,3 +48,7 @@ hid-add-asus-aio-keyboard-model-ak1d.patch x86-microcode-microcode_core.c-simple_strtoul-cleanup.patch x86-microcode-sanitize-per-cpu-microcode-reloading-interface.patch mm-hugetlbfs-close-race-during-teardown-of-hugetlbfs-shared-page-tables.patch +target-add-range-checking-to-unmap-emulation.patch +target-fix-reading-of-data-length-fields-for-unmap-commands.patch +target-fix-possible-integer-underflow-in-unmap-emulation.patch +target-check-number-of-unmap-descriptors-against-our-limit.patch diff --git a/queue-3.4/target-add-range-checking-to-unmap-emulation.patch b/queue-3.4/target-add-range-checking-to-unmap-emulation.patch new file mode 100644 index 00000000000..2587041f6f2 --- /dev/null +++ b/queue-3.4/target-add-range-checking-to-unmap-emulation.patch @@ -0,0 +1,43 @@ +From: Roland Dreier +Date: Mon, 16 Jul 2012 15:34:22 -0700 +Subject: target: Add range checking to UNMAP emulation + +From: Roland Dreier + +commit 2594e29865c291db162313187612cd9f14538f33 upstream. + +When processing an UNMAP command, we need to make sure that the number +of blocks we're asked to UNMAP does not exceed our reported maximum +number of blocks per UNMAP, and that the range of blocks we're +unmapping doesn't go past the end of the device. + +Signed-off-by: Roland Dreier +Signed-off-by: Nicholas Bellinger +[bwh: Backported to 3.2: adjust filename, context] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/target/target_core_cdb.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/target/target_core_cdb.c ++++ b/drivers/target/target_core_cdb.c +@@ -1053,6 +1053,18 @@ int target_emulate_unmap(struct se_task + pr_debug("UNMAP: Using lba: %llu and range: %u\n", + (unsigned long long)lba, range); + ++ if (range > dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count) { ++ cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ if (lba + range > dev->transport->get_blocks(dev) + 1) { ++ cmd->scsi_sense_reason = TCM_ADDRESS_OUT_OF_RANGE; ++ ret = -EINVAL; ++ goto err; ++ } ++ + ret = dev->transport->do_discard(dev, lba, range); + if (ret < 0) { + pr_err("blkdev_issue_discard() failed: %d\n", diff --git a/queue-3.4/target-check-number-of-unmap-descriptors-against-our-limit.patch b/queue-3.4/target-check-number-of-unmap-descriptors-against-our-limit.patch new file mode 100644 index 00000000000..d9a9884ee2f --- /dev/null +++ b/queue-3.4/target-check-number-of-unmap-descriptors-against-our-limit.patch @@ -0,0 +1,34 @@ +From: Roland Dreier +Date: Mon, 16 Jul 2012 15:34:25 -0700 +Subject: target: Check number of unmap descriptors against our limit + +From: Roland Dreier + +commit 7409a6657aebf8be74c21d0eded80709b27275cb upstream. + +Fail UNMAP commands that have more than our reported limit on unmap +descriptors. + +Signed-off-by: Roland Dreier +Signed-off-by: Nicholas Bellinger +[bwh: Backported to 3.2: adjust filename] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/target/target_core_cdb.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/target/target_core_cdb.c ++++ b/drivers/target/target_core_cdb.c +@@ -1041,6 +1041,11 @@ int target_emulate_unmap(struct se_task + bd_dl = get_unaligned_be16(&buf[2]); + + size = min(size - 8, bd_dl); ++ if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { ++ cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; ++ ret = -EINVAL; ++ goto err; ++ } + + /* First UNMAP block descriptor starts at 8 byte offset */ + ptr = &buf[8]; diff --git a/queue-3.4/target-fix-possible-integer-underflow-in-unmap-emulation.patch b/queue-3.4/target-fix-possible-integer-underflow-in-unmap-emulation.patch new file mode 100644 index 00000000000..25aa6232a23 --- /dev/null +++ b/queue-3.4/target-fix-possible-integer-underflow-in-unmap-emulation.patch @@ -0,0 +1,71 @@ +From: Roland Dreier +Date: Mon, 16 Jul 2012 15:34:24 -0700 +Subject: target: Fix possible integer underflow in UNMAP emulation + +From: Roland Dreier + +commit b7fc7f3777582dea85156a821d78a522a0c083aa upstream. + +It's possible for an initiator to send us an UNMAP command with a +descriptor that is less than 8 bytes; in that case it's really bad for +us to set an unsigned int to that value, subtract 8 from it, and then +use that as a limit for our loop (since the value will wrap around to +a huge positive value). + +Fix this by making size be signed and only looping if size >= 16 (ie +if we have at least a full descriptor available). + +Also remove offset as an obfuscated name for the constant 8. + +Signed-off-by: Roland Dreier +Signed-off-by: Nicholas Bellinger +[bwh: Backported to 3.2: adjust filename, context] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/target/target_core_cdb.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +--- a/drivers/target/target_core_cdb.c ++++ b/drivers/target/target_core_cdb.c +@@ -1023,9 +1023,10 @@ int target_emulate_unmap(struct se_task + struct se_device *dev = cmd->se_dev; + unsigned char *buf, *ptr = NULL; + sector_t lba; +- unsigned int size = cmd->data_length, range; +- int ret = 0, offset; +- unsigned short dl, bd_dl; ++ int size = cmd->data_length; ++ u32 range; ++ int ret = 0; ++ int dl, bd_dl; + + if (!dev->transport->do_discard) { + pr_err("UNMAP emulation not supported for: %s\n", +@@ -1034,20 +1035,19 @@ int target_emulate_unmap(struct se_task + return -ENOSYS; + } + +- /* First UNMAP block descriptor starts at 8 byte offset */ +- offset = 8; +- size -= 8; +- + buf = transport_kmap_data_sg(cmd); + + dl = get_unaligned_be16(&buf[0]); + bd_dl = get_unaligned_be16(&buf[2]); + +- ptr = &buf[offset]; +- pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu" ++ size = min(size - 8, bd_dl); ++ ++ /* First UNMAP block descriptor starts at 8 byte offset */ ++ ptr = &buf[8]; ++ pr_debug("UNMAP: Sub: %s Using dl: %u bd_dl: %u size: %u" + " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr); + +- while (size) { ++ while (size >= 16) { + lba = get_unaligned_be64(&ptr[0]); + range = get_unaligned_be32(&ptr[8]); + pr_debug("UNMAP: Using lba: %llu and range: %u\n", diff --git a/queue-3.4/target-fix-reading-of-data-length-fields-for-unmap-commands.patch b/queue-3.4/target-fix-reading-of-data-length-fields-for-unmap-commands.patch new file mode 100644 index 00000000000..f6f4efd41c5 --- /dev/null +++ b/queue-3.4/target-fix-reading-of-data-length-fields-for-unmap-commands.patch @@ -0,0 +1,47 @@ +From: Roland Dreier +Date: Mon, 16 Jul 2012 15:34:23 -0700 +Subject: target: Fix reading of data length fields for UNMAP commands + +From: Roland Dreier + +commit 1a5fa4576ec8a462313c7516b31d7453481ddbe8 upstream. + +The UNMAP DATA LENGTH and UNMAP BLOCK DESCRIPTOR DATA LENGTH fields +are in the unmap descriptor (the payload transferred to our data out +buffer), not in the CDB itself. Read them from the correct place in +target_emulated_unmap. + +Signed-off-by: Roland Dreier +Signed-off-by: Nicholas Bellinger +[bwh: Backported to 3.2: adjust filename, context] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/target/target_core_cdb.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/target/target_core_cdb.c ++++ b/drivers/target/target_core_cdb.c +@@ -1022,7 +1022,6 @@ int target_emulate_unmap(struct se_task + struct se_cmd *cmd = task->task_se_cmd; + struct se_device *dev = cmd->se_dev; + unsigned char *buf, *ptr = NULL; +- unsigned char *cdb = &cmd->t_task_cdb[0]; + sector_t lba; + unsigned int size = cmd->data_length, range; + int ret = 0, offset; +@@ -1038,11 +1037,12 @@ int target_emulate_unmap(struct se_task + /* First UNMAP block descriptor starts at 8 byte offset */ + offset = 8; + size -= 8; +- dl = get_unaligned_be16(&cdb[0]); +- bd_dl = get_unaligned_be16(&cdb[2]); + + buf = transport_kmap_data_sg(cmd); + ++ dl = get_unaligned_be16(&buf[0]); ++ bd_dl = get_unaligned_be16(&buf[2]); ++ + ptr = &buf[offset]; + pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu" + " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr);