Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Rajashekhara, Mahesh and committed by
James Bottomley
da3cc679 1fc8010a

+34
+34
drivers/scsi/aacraid/aachba.c
··· 1608 1608 int status; 1609 1609 struct aac_dev *dev; 1610 1610 struct fib * cmd_fibcontext; 1611 + int cid; 1611 1612 1612 1613 dev = (struct aac_dev *)scsicmd->device->host->hostdata; 1613 1614 /* ··· 1658 1657 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; 1659 1658 break; 1660 1659 } 1660 + 1661 + if ((lba + count) > (dev->fsa_dev[scmd_id(scsicmd)].size)) { 1662 + cid = scmd_id(scsicmd); 1663 + dprintk((KERN_DEBUG "aacraid: Illegal lba\n")); 1664 + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | 1665 + SAM_STAT_CHECK_CONDITION; 1666 + set_sense(&dev->fsa_dev[cid].sense_data, 1667 + HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE, 1668 + ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0); 1669 + memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, 1670 + min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data), 1671 + SCSI_SENSE_BUFFERSIZE)); 1672 + scsicmd->scsi_done(scsicmd); 1673 + return 1; 1674 + } 1675 + 1661 1676 dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.\n", 1662 1677 smp_processor_id(), (unsigned long long)lba, jiffies)); 1663 1678 if (aac_adapter_bounds(dev,scsicmd,lba)) ··· 1715 1698 int status; 1716 1699 struct aac_dev *dev; 1717 1700 struct fib * cmd_fibcontext; 1701 + int cid; 1718 1702 1719 1703 dev = (struct aac_dev *)scsicmd->device->host->hostdata; 1720 1704 /* ··· 1755 1737 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; 1756 1738 fua = scsicmd->cmnd[1] & 0x8; 1757 1739 } 1740 + 1741 + if ((lba + count) > (dev->fsa_dev[scmd_id(scsicmd)].size)) { 1742 + cid = scmd_id(scsicmd); 1743 + dprintk((KERN_DEBUG "aacraid: Illegal lba\n")); 1744 + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | 1745 + SAM_STAT_CHECK_CONDITION; 1746 + set_sense(&dev->fsa_dev[cid].sense_data, 1747 + HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE, 1748 + ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0); 1749 + memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, 1750 + min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data), 1751 + SCSI_SENSE_BUFFERSIZE)); 1752 + scsicmd->scsi_done(scsicmd); 1753 + return 1; 1754 + } 1755 + 1758 1756 dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n", 1759 1757 smp_processor_id(), (unsigned long long)lba, jiffies)); 1760 1758 if (aac_adapter_bounds(dev,scsicmd,lba))