aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2012-09-07 11:30:39 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2012-09-17 20:13:37 -0400
commit7a3f369ce31694017996524a1cdb08208a839077 (patch)
tree0c191ecc298ae9cf3d0f29a446f6c43e9b9e630c /drivers/target
parentffe7b0e9326d9c68f5688bef691dd49f1e0d3651 (diff)
target: fix truncation of mode data, support zero allocation length
The offset was not bumped back to the full size after writing the header of the MODE SENSE response, so the last 1 or 2 bytes were not copied. On top of this, support zero-length requests by checking for the return value of transport_kmap_data_sg. Testcase: sg_raw -r20 /dev/sdb 5a 00 0a 00 00 00 00 00 14 00 last byte should be 0x1e it is 0x00 without the patch it is correct with the patch 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.c17
1 files changed, 7 insertions, 10 deletions
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index b3d8fd260374..9229bd9ad61b 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -784,7 +784,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
784 unsigned char *rbuf; 784 unsigned char *rbuf;
785 int type = dev->transport->get_device_type(dev); 785 int type = dev->transport->get_device_type(dev);
786 int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10); 786 int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10);
787 int offset = ten ? 8 : 4; 787 u32 offset = ten ? 8 : 4;
788 int length = 0; 788 int length = 0;
789 unsigned char buf[SE_MODE_PAGE_BUF]; 789 unsigned char buf[SE_MODE_PAGE_BUF];
790 790
@@ -817,6 +817,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
817 offset -= 2; 817 offset -= 2;
818 buf[0] = (offset >> 8) & 0xff; 818 buf[0] = (offset >> 8) & 0xff;
819 buf[1] = offset & 0xff; 819 buf[1] = offset & 0xff;
820 offset += 2;
820 821
821 if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || 822 if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
822 (cmd->se_deve && 823 (cmd->se_deve &&
@@ -826,13 +827,10 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
826 if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) && 827 if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
827 (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0)) 828 (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
828 spc_modesense_dpofua(&buf[3], type); 829 spc_modesense_dpofua(&buf[3], type);
829
830 if ((offset + 2) > cmd->data_length)
831 offset = cmd->data_length;
832
833 } else { 830 } else {
834 offset -= 1; 831 offset -= 1;
835 buf[0] = offset & 0xff; 832 buf[0] = offset & 0xff;
833 offset += 1;
836 834
837 if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || 835 if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
838 (cmd->se_deve && 836 (cmd->se_deve &&
@@ -842,14 +840,13 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
842 if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) && 840 if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
843 (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0)) 841 (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
844 spc_modesense_dpofua(&buf[2], type); 842 spc_modesense_dpofua(&buf[2], type);
845
846 if ((offset + 1) > cmd->data_length)
847 offset = cmd->data_length;
848 } 843 }
849 844
850 rbuf = transport_kmap_data_sg(cmd); 845 rbuf = transport_kmap_data_sg(cmd);
851 memcpy(rbuf, buf, offset); 846 if (rbuf) {
852 transport_kunmap_data_sg(cmd); 847 memcpy(rbuf, buf, min(offset, cmd->data_length));
848 transport_kunmap_data_sg(cmd);
849 }
853 850
854 target_complete_cmd(cmd, GOOD); 851 target_complete_cmd(cmd, GOOD);
855 return 0; 852 return 0;