[SCSI] aacraid: prohibit access to array container space
Problem description: -------------------- The issue reported by one of the customer was able to read LBA beyond the array reported size with "sg_read" utility. If N is the last block address reported, then should not be able to read past N, i.e. N+1. But in their case, reported last LBA=143134719. So should not have been able to read with LBA=143134720, but it is read without failure, which means reported size to the OS is not correct and is less than the actual last block address. Solution: --------- Firmware layer exposes lesser container capacity than the actual one. It exposes [Actual size - Spitfire space(10MB)] to the OS, IO's to the 10MB should be prohibited from the Linux driver. Driver checks LBA boundary, if its greater than the array reported size then sets sensekey to HARDWARE_ERROR and sends the notification to the MID layer. Signed-off-by: Mahesh Rajashekhara <aacraid@adaptec.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
parent
1fc8010a5d
commit
da3cc679b2
1 changed files with 34 additions and 0 deletions
|
@ -1608,6 +1608,7 @@ static int aac_read(struct scsi_cmnd * scsicmd)
|
||||||
int status;
|
int status;
|
||||||
struct aac_dev *dev;
|
struct aac_dev *dev;
|
||||||
struct fib * cmd_fibcontext;
|
struct fib * cmd_fibcontext;
|
||||||
|
int cid;
|
||||||
|
|
||||||
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
|
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
|
||||||
/*
|
/*
|
||||||
|
@ -1657,6 +1658,22 @@ static int aac_read(struct scsi_cmnd * scsicmd)
|
||||||
count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
|
count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((lba + count) > (dev->fsa_dev[scmd_id(scsicmd)].size)) {
|
||||||
|
cid = scmd_id(scsicmd);
|
||||||
|
dprintk((KERN_DEBUG "aacraid: Illegal lba\n"));
|
||||||
|
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
|
||||||
|
SAM_STAT_CHECK_CONDITION;
|
||||||
|
set_sense(&dev->fsa_dev[cid].sense_data,
|
||||||
|
HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
|
||||||
|
ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
|
||||||
|
memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
|
||||||
|
min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
|
||||||
|
SCSI_SENSE_BUFFERSIZE));
|
||||||
|
scsicmd->scsi_done(scsicmd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.\n",
|
dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.\n",
|
||||||
smp_processor_id(), (unsigned long long)lba, jiffies));
|
smp_processor_id(), (unsigned long long)lba, jiffies));
|
||||||
if (aac_adapter_bounds(dev,scsicmd,lba))
|
if (aac_adapter_bounds(dev,scsicmd,lba))
|
||||||
|
@ -1698,6 +1715,7 @@ static int aac_write(struct scsi_cmnd * scsicmd)
|
||||||
int status;
|
int status;
|
||||||
struct aac_dev *dev;
|
struct aac_dev *dev;
|
||||||
struct fib * cmd_fibcontext;
|
struct fib * cmd_fibcontext;
|
||||||
|
int cid;
|
||||||
|
|
||||||
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
|
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
|
||||||
/*
|
/*
|
||||||
|
@ -1737,6 +1755,22 @@ static int aac_write(struct scsi_cmnd * scsicmd)
|
||||||
count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
|
count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
|
||||||
fua = scsicmd->cmnd[1] & 0x8;
|
fua = scsicmd->cmnd[1] & 0x8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((lba + count) > (dev->fsa_dev[scmd_id(scsicmd)].size)) {
|
||||||
|
cid = scmd_id(scsicmd);
|
||||||
|
dprintk((KERN_DEBUG "aacraid: Illegal lba\n"));
|
||||||
|
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
|
||||||
|
SAM_STAT_CHECK_CONDITION;
|
||||||
|
set_sense(&dev->fsa_dev[cid].sense_data,
|
||||||
|
HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
|
||||||
|
ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
|
||||||
|
memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
|
||||||
|
min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
|
||||||
|
SCSI_SENSE_BUFFERSIZE));
|
||||||
|
scsicmd->scsi_done(scsicmd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",
|
dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",
|
||||||
smp_processor_id(), (unsigned long long)lba, jiffies));
|
smp_processor_id(), (unsigned long long)lba, jiffies));
|
||||||
if (aac_adapter_bounds(dev,scsicmd,lba))
|
if (aac_adapter_bounds(dev,scsicmd,lba))
|
||||||
|
|
Loading…
Reference in a new issue