| From 8cd79f24350826b81e16990d9e12bc878e67d385 Mon Sep 17 00:00:00 2001 |
| From: Nicholas Bellinger <nab@linux-iscsi.org> |
| Date: Mon, 24 Oct 2011 13:35:37 -0700 |
| Subject: tcm_loop: Add explict read buffer memset for SCF_SCSI_CONTROL_SG_IO_CDB |
| |
| From: Nicholas Bellinger <nab@linux-iscsi.org> |
| |
| 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 | 18 ++++++++++++++++++ |
| 1 file changed, 18 insertions(+) |
| |
| --- 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 s |
| 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), |