[SCSI] eliminate potential kmalloc failure in scsi_get_vpd_page()
[pandora-kernel.git] / drivers / scsi / scsi.c
index a60da55..513661f 100644 (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);