aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2008-02-24 18:25:23 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-07 13:15:40 -0400
commitb271f1c881ff301ba1fbb52698d4f2b91858f421 (patch)
tree630df6fc88f323fb491ba9ed4bb282c804ae136d
parentb174be02f3634460ac215d249617dee5ae446ae1 (diff)
[SCSI] aacraid: READ_CAPACITY_16 shouldn't trust allocation length in cdb
When aacraid spoofs READ_CAPACITY_16, it assumes that the data length in the sg list is equal to allocation length in cdb. But sg can put any value in scb so the driver needs to check both the data length in the sg list and allocation length in cdb. If allocation length is larger than the response length that the driver expects, it clears the data buffer in the sg list to zero but it doesn't need to do. Just setting resid is fine. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Acked-by: Mark Salyzyn <Mark_Salyzyn@adaptec.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--drivers/scsi/aacraid/aachba.c22
1 files changed, 11 insertions, 11 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index c05092fd3a9d..b9fc9b1dde67 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -2047,6 +2047,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
2047 { 2047 {
2048 u64 capacity; 2048 u64 capacity;
2049 char cp[13]; 2049 char cp[13];
2050 unsigned int alloc_len;
2050 2051
2051 dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n")); 2052 dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n"));
2052 capacity = fsa_dev_ptr[cid].size - 1; 2053 capacity = fsa_dev_ptr[cid].size - 1;
@@ -2063,18 +2064,17 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
2063 cp[10] = 2; 2064 cp[10] = 2;
2064 cp[11] = 0; 2065 cp[11] = 0;
2065 cp[12] = 0; 2066 cp[12] = 0;
2066 aac_internal_transfer(scsicmd, cp, 0,
2067 min_t(size_t, scsicmd->cmnd[13], sizeof(cp)));
2068 if (sizeof(cp) < scsicmd->cmnd[13]) {
2069 unsigned int len, offset = sizeof(cp);
2070 2067
2071 memset(cp, 0, offset); 2068 alloc_len = ((scsicmd->cmnd[10] << 24)
2072 do { 2069 + (scsicmd->cmnd[11] << 16)
2073 len = min_t(size_t, scsicmd->cmnd[13] - offset, 2070 + (scsicmd->cmnd[12] << 8) + scsicmd->cmnd[13]);
2074 sizeof(cp)); 2071
2075 aac_internal_transfer(scsicmd, cp, offset, len); 2072 alloc_len = min_t(size_t, alloc_len, sizeof(cp));
2076 } while ((offset += len) < scsicmd->cmnd[13]); 2073 aac_internal_transfer(scsicmd, cp, 0, alloc_len);
2077 } 2074
2075 if (alloc_len < scsi_bufflen(scsicmd))
2076 scsi_set_resid(scsicmd,
2077 scsi_bufflen(scsicmd) - alloc_len);
2078 2078
2079 /* Do not cache partition table for arrays */ 2079 /* Do not cache partition table for arrays */
2080 scsicmd->device->removable = 1; 2080 scsicmd->device->removable = 1;