path: root/drivers/target/loopback
diff options
authorNicholas Bellinger <nab@linux-iscsi.org>2011-10-24 13:35:37 -0700
committerNicholas Bellinger <nab@linux-iscsi.org>2011-10-26 20:42:13 +0000
commit8cd79f24350826b81e16990d9e12bc878e67d385 (patch)
tree14421b42c8c7eeb566e5793c1dfd45d051cd74d6 /drivers/target/loopback
parentc9abb9bb0b8451588509192bd53005d65c02986c (diff)
tcm_loop: Add explict read buffer memset for SCF_SCSI_CONTROL_SG_IO_CDB
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> Cc: stable@kernel.org Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target/loopback')
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index b15d8cbf630..3c9c318f66e 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -174,6 +174,24 @@ static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd)
sgl_bidi = sdb->table.sgl;
sgl_bidi_count = sdb->table.nents;
+ /*
+ * 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));
+ }
+ }
/* Tell the core about our preallocated memory */
ret = transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc),