diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2012-09-07 17:30:38 +0200 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2012-09-17 17:13:36 -0700 |
commit | ffe7b0e9326d9c68f5688bef691dd49f1e0d3651 (patch) | |
tree | f180001bbe2685c8388c372766e6884f2cb7845e /drivers/target | |
parent | bf11eefcb1dc1326341ebdc44566ad08bee3f539 (diff) |
target: support zero allocation length in INQUIRY
INQUIRY processing already uses an on-heap bounce buffer for loopback,
but not for other fabrics. Switch this to a cheaper on-stack bounce
buffer, similar to the one used by MODE SENSE and REQUEST SENSE, and
use it unconditionally. With this in place, zero allocation length is
handled simply by checking the return address of transport_kmap_data_sg.
Testcase: sg_raw /dev/sdb 12 00 83 00 00 00
should fail with ILLEGAL REQUEST / INVALID FIELD IN CDB sense
does not fail without the patch
fails correctly with the series
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/target_core_spc.c | 31 |
1 files changed, 6 insertions, 25 deletions
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 388a922c8f6..b3d8fd26037 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -600,30 +600,11 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg; - unsigned char *buf, *map_buf; + unsigned char *rbuf; unsigned char *cdb = cmd->t_task_cdb; + unsigned char buf[SE_INQUIRY_BUF]; int p, ret; - map_buf = transport_kmap_data_sg(cmd); - /* - * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we - * know we actually allocated a full page. Otherwise, if the - * data buffer is too small, allocate a temporary buffer so we - * don't have to worry about overruns in all our INQUIRY - * emulation handling. - */ - if (cmd->data_length < SE_INQUIRY_BUF && - (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) { - buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL); - if (!buf) { - transport_kunmap_data_sg(cmd); - cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -ENOMEM; - } - } else { - buf = map_buf; - } - if (dev == tpg->tpg_virt_lun0.lun_se_dev) buf[0] = 0x3f; /* Not connected */ else @@ -655,11 +636,11 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) ret = -EINVAL; out: - if (buf != map_buf) { - memcpy(map_buf, buf, cmd->data_length); - kfree(buf); + rbuf = transport_kmap_data_sg(cmd); + if (rbuf) { + memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); + transport_kunmap_data_sg(cmd); } - transport_kunmap_data_sg(cmd); if (!ret) target_complete_cmd(cmd, GOOD); |