[SCSI] eliminate potential kmalloc failure in scsi_get_vpd_page()

The best way to fix this is to eliminate the intenal kmalloc() and
make the caller allocate the required amount of storage.

Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
James Bottomley
2009-11-03 12:33:07 -06:00
parent 534ef056db
commit e3deec0905
4 changed files with 36 additions and 43 deletions

View File

@@ -1026,55 +1026,39 @@ static int scsi_vpd_inquiry(struct scsi_device *sdev, unsigned char *buffer,
* responsible for calling kfree() on this pointer when it is no longer
* needed. If we cannot retrieve the VPD page this routine returns %NULL.
*/
unsigned char *scsi_get_vpd_page(struct scsi_device *sdev, u8 page)
int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf,
int buf_len)
{
int i, result;
unsigned int len;
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, init_vpd_len);
result = scsi_vpd_inquiry(sdev, buf, 0, buf_len);
if (result)
goto fail;
/* If the user actually wanted this page, we can skip the rest */
if (page == 0)
return buf;
return -EINVAL;
for (i = 0; i < buf[3]; i++)
for (i = 0; i < min((int)buf[3], buf_len - 4); i++)
if (buf[i + 4] == page)
goto found;
if (i < buf[3] && i > buf_len)
/* ran off the end of the buffer, give us benefit of doubt */
goto found;
/* The device claims it doesn't support the requested page */
goto fail;
found:
result = scsi_vpd_inquiry(sdev, buf, page, 255);
result = scsi_vpd_inquiry(sdev, buf, page, buf_len);
if (result)
goto fail;
/*
* Some pages are longer than 255 bytes. The actual length of
* the page is returned in the header.
*/
len = ((buf[2] << 8) | buf[3]) + 4;
if (len <= init_vpd_len)
return buf;
kfree(buf);
buf = kmalloc(len, GFP_KERNEL);
result = scsi_vpd_inquiry(sdev, buf, page, len);
if (result)
goto fail;
return buf;
return 0;
fail:
kfree(buf);
return NULL;
return -EINVAL;
}
EXPORT_SYMBOL_GPL(scsi_get_vpd_page);