aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2009-08-11 10:59:09 -0500
committerJames Bottomley <James.Bottomley@suse.de>2009-08-22 17:52:23 -0500
commit95a3639e275fb7aec5c9a2116c88a2cdd23e0b8b (patch)
tree115b3d4fecf7e9089000c9f4bf5558be99670bf0 /drivers/scsi
parent[SCSI] reservation conflict after timeout causes device to be taken offline (diff)
downloadlinux-dev-95a3639e275fb7aec5c9a2116c88a2cdd23e0b8b.tar.xz
linux-dev-95a3639e275fb7aec5c9a2116c88a2cdd23e0b8b.zip
[SCSI] fix bugs in scsi_vpd_inquiry()
Universally, SCSI functions assume the lengths fed in are those of the buffer to DMA data to, not the lengths of the data minus the header. scsi_vpd_inquiry() assumed the latter and got it wrong, so fix up all the functions to use the correct assumption (and fix a bug where INQUIRY in SCSI-2 dcannot go over 255). [jejb: Matthew posted an identical version of this at the same time I did] Signed-off-by: Matthew Wilcox <matthew@wil.cx> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 2de5f3ad640b..b6e03074cb8f 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -994,7 +994,7 @@ static int scsi_vpd_inquiry(struct scsi_device *sdev, unsigned char *buffer,
* all the existing users tried this hard.
*/
result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer,
- len + 4, NULL, 30 * HZ, 3, NULL);
+ len, NULL, 30 * HZ, 3, NULL);
if (result)
return result;
@@ -1021,13 +1021,14 @@ unsigned char *scsi_get_vpd_page(struct scsi_device *sdev, u8 page)
{
int i, result;
unsigned int len;
- unsigned char *buf = kmalloc(259, GFP_KERNEL);
+ const unsigned int init_vpd_len = 255;
+ unsigned char *buf = kmalloc(init_vpd_len, GFP_KERNEL);
if (!buf)
return NULL;
/* Ask for all the pages supported by this device */
- result = scsi_vpd_inquiry(sdev, buf, 0, 255);
+ result = scsi_vpd_inquiry(sdev, buf, 0, init_vpd_len);
if (result)
goto fail;
@@ -1050,12 +1051,12 @@ unsigned char *scsi_get_vpd_page(struct scsi_device *sdev, u8 page)
* Some pages are longer than 255 bytes. The actual length of
* the page is returned in the header.
*/
- len = (buf[2] << 8) | buf[3];
- if (len <= 255)
+ len = ((buf[2] << 8) | buf[3]) + 4;
+ if (len <= init_vpd_len)
return buf;
kfree(buf);
- buf = kmalloc(len + 4, GFP_KERNEL);
+ buf = kmalloc(len, GFP_KERNEL);
result = scsi_vpd_inquiry(sdev, buf, page, len);
if (result)
goto fail;