]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
target: fix truncation of mode data, support zero allocation length
authorPaolo Bonzini <pbonzini@redhat.com>
Fri, 7 Sep 2012 15:30:39 +0000 (17:30 +0200)
committerNicholas Bellinger <nab@linux-iscsi.org>
Fri, 7 Sep 2012 18:52:40 +0000 (11:52 -0700)
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>
drivers/target/target_core_spc.c

index e27701b83641bdcff5c9bb369bfaccea5b0401a0..f23dda3811c917883fe1dc265b05235e448cebb5 100644 (file)
@@ -784,7 +784,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
        unsigned char *rbuf;
        int type = dev->transport->get_device_type(dev);
        int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10);
-       int offset = ten ? 8 : 4;
+       u32 offset = ten ? 8 : 4;
        int length = 0;
        unsigned char buf[SE_MODE_PAGE_BUF];
 
@@ -817,6 +817,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
                offset -= 2;
                buf[0] = (offset >> 8) & 0xff;
                buf[1] = offset & 0xff;
+               offset += 2;
 
                if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
                    (cmd->se_deve &&
@@ -826,13 +827,10 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
                if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
                    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
                        spc_modesense_dpofua(&buf[3], type);
-
-               if ((offset + 2) > cmd->data_length)
-                       offset = cmd->data_length;
-
        } else {
                offset -= 1;
                buf[0] = offset & 0xff;
+               offset += 1;
 
                if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
                    (cmd->se_deve &&
@@ -842,14 +840,13 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
                if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
                    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
                        spc_modesense_dpofua(&buf[2], type);
-
-               if ((offset + 1) > cmd->data_length)
-                       offset = cmd->data_length;
        }
 
        rbuf = transport_kmap_data_sg(cmd);
-       memcpy(rbuf, buf, offset);
-       transport_kunmap_data_sg(cmd);
+       if (rbuf) {
+               memcpy(rbuf, buf, min(offset, cmd->data_length));
+               transport_kunmap_data_sg(cmd);
+       }
 
        target_complete_cmd(cmd, GOOD);
        return 0;