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>
This commit is contained in:
@@ -174,6 +174,24 @@ static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd)
|
|||||||
sgl_bidi = sdb->table.sgl;
|
sgl_bidi = sdb->table.sgl;
|
||||||
sgl_bidi_count = sdb->table.nents;
|
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 */
|
/* Tell the core about our preallocated memory */
|
||||||
ret = transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc),
|
ret = transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc),
|
||||||
|
Reference in New Issue
Block a user