Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit da3cc679 authored by Rajashekhara, Mahesh's avatar Rajashekhara, Mahesh Committed by James Bottomley
Browse files

[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: default avatarMahesh Rajashekhara <aacraid@adaptec.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 1fc8010a
Loading
Loading
Loading
Loading
+34 −0
Original line number Original line Diff line number Diff line
@@ -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))