summaryrefslogtreecommitdiff
path: root/drivers/target
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-10-24 13:35:37 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2011-11-11 09:37:01 -0800
commitfef547148349098f58bcea1c6cda5be1f6f8719c (patch)
tree2521e4b3969b88c0c02902a44315ceedd78577d0 /drivers/target
parent24b791339f0e80761de402cbb13ff2ddb19b8c03 (diff)
tcm_loop: Add explict read buffer memset for SCF_SCSI_CONTROL_SG_IO_CDB
commit 8cd79f24350826b81e16990d9e12bc878e67d385 upstream. This patch addresses an issue with buggy userspace code sending I/O via scsi-generic that does not explictly clear their associated read buffers. It adds an explict memset of the first SGL entry within tcm_loop_new_cmd_map() for SCF_SCSI_CONTROL_SG_IO_CDB payloads that are currently guaranteed to be a single SGL by target-core code. This issue is a side effect of the v3.1-rc1 merge to remove the extra memcpy between certain control CDB types using a contigious + cleared buffer in target-core, and performing a memcpy into the SGL list within tcm_loop. It was originally mainfesting itself by udev + scsi_id + scsi-generic not properly setting up the expected /dev/disk/by-id/ symlinks because the INQUIRY payload was containing extra bogus data preventing the proper NAA IEEE WWN from being parsed by userspace. Cc: Christoph Hellwig <hch@lst.de> Cc: Andy Grover <agrover@redhat.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/loopback/tcm_loop.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 70c2e7fa6664..4b5421b391da 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -127,6 +127,24 @@ static struct se_cmd *tcm_loop_allocate_core_cmd(
set_host_byte(sc, DID_NO_CONNECT);
return NULL;
}
+ /*
+ * Because some userspace code via scsi-generic do not memset their
+ * associated read buffers, go ahead and do that here for type
+ * SCF_SCSI_CONTROL_SG_IO_CDB. Also note that this is currently
+ * guaranteed to be a single SGL for SCF_SCSI_CONTROL_SG_IO_CDB
+ * by target core in transport_generic_allocate_tasks() ->
+ * transport_generic_cmd_sequencer().
+ */
+ if (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB &&
+ se_cmd->data_direction == DMA_FROM_DEVICE) {
+ struct scatterlist *sg = scsi_sglist(sc);
+ unsigned char *buf = kmap(sg_page(sg)) + sg->offset;
+
+ if (buf != NULL) {
+ memset(buf, 0, sg->length);
+ kunmap(sg_page(sg));
+ }
+ }
transport_device_setup_cmd(se_cmd);
return se_cmd;