Skip to content

Commit

Permalink
[SCSI] aacraid: READ_CAPACITY_16 shouldn't trust allocation length in…
Browse files Browse the repository at this point in the history
… 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>
  • Loading branch information
FUJITA Tomonori authored and James Bottomley committed Apr 7, 2008
1 parent b174be0 commit b271f1c
Showing 1 changed file with 11 additions and 11 deletions.
22 changes: 11 additions & 11 deletions drivers/scsi/aacraid/aachba.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down

0 comments on commit b271f1c

Please sign in to comment.