From b271f1c881ff301ba1fbb52698d4f2b91858f421 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sun, 24 Feb 2008 15:25:23 -0800 Subject: [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 Acked-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/scsi/aacraid/aachba.c') 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) { u64 capacity; char cp[13]; + unsigned int alloc_len; dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n")); capacity = fsa_dev_ptr[cid].size - 1; @@ -2063,18 +2064,17 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) cp[10] = 2; cp[11] = 0; cp[12] = 0; - aac_internal_transfer(scsicmd, cp, 0, - min_t(size_t, scsicmd->cmnd[13], sizeof(cp))); - if (sizeof(cp) < scsicmd->cmnd[13]) { - unsigned int len, offset = sizeof(cp); - memset(cp, 0, offset); - do { - len = min_t(size_t, scsicmd->cmnd[13] - offset, - sizeof(cp)); - aac_internal_transfer(scsicmd, cp, offset, len); - } while ((offset += len) < scsicmd->cmnd[13]); - } + alloc_len = ((scsicmd->cmnd[10] << 24) + + (scsicmd->cmnd[11] << 16) + + (scsicmd->cmnd[12] << 8) + scsicmd->cmnd[13]); + + alloc_len = min_t(size_t, alloc_len, sizeof(cp)); + aac_internal_transfer(scsicmd, cp, 0, alloc_len); + + if (alloc_len < scsi_bufflen(scsicmd)) + scsi_set_resid(scsicmd, + scsi_bufflen(scsicmd) - alloc_len); /* Do not cache partition table for arrays */ scsicmd->device->removable = 1; -- cgit v1.2.3