]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
tcm_loop: Add explict read buffer memset for SCF_SCSI_CONTROL_SG_IO_CDB
authorNicholas Bellinger <nab@linux-iscsi.org>
Mon, 24 Oct 2011 20:35:37 +0000 (13:35 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 11 Nov 2011 17:37:01 +0000 (09:37 -0800)
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>
drivers/target/loopback/tcm_loop.c

index 70c2e7fa66643f7a7cdf040c62d74e977d7b9d1b..4b5421b391da0500ea1e1b7f8cc8bf227415d40a 100644 (file)
@@ -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;