瀏覽代碼

isight_firmware: Avoid crash on loading invalid firmware

Different tools generate slightly different formats of the isight
firmware. Ensure that the firmware buffer is not overrun, while still
ensuring that the correct amount of data is written if trailing data is
present.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
Report-by: Justin Mattock <justinmattock@gmail.com>
Tested-by: Justin Mattock <justinmattock@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Matthew Garrett 17 年之前
父節點
當前提交
62b5884875
共有 1 個文件被更改,包括 16 次插入7 次删除
  1. 16 7
      drivers/usb/misc/isight_firmware.c

+ 16 - 7
drivers/usb/misc/isight_firmware.c

@@ -39,9 +39,12 @@ static int isight_firmware_load(struct usb_interface *intf,
 	struct usb_device *dev = interface_to_usbdev(intf);
 	struct usb_device *dev = interface_to_usbdev(intf);
 	int llen, len, req, ret = 0;
 	int llen, len, req, ret = 0;
 	const struct firmware *firmware;
 	const struct firmware *firmware;
-	unsigned char *buf;
+	unsigned char *buf = kmalloc(50, GFP_KERNEL);
 	unsigned char data[4];
 	unsigned char data[4];
-	char *ptr;
+	u8 *ptr;
+
+	if (!buf)
+		return -ENOMEM;
 
 
 	if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) {
 	if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) {
 		printk(KERN_ERR "Unable to load isight firmware\n");
 		printk(KERN_ERR "Unable to load isight firmware\n");
@@ -59,7 +62,7 @@ static int isight_firmware_load(struct usb_interface *intf,
 		goto out;
 		goto out;
 	}
 	}
 
 
-	while (1) {
+	while (ptr+4 <= firmware->data+firmware->size) {
 		memcpy(data, ptr, 4);
 		memcpy(data, ptr, 4);
 		len = (data[0] << 8 | data[1]);
 		len = (data[0] << 8 | data[1]);
 		req = (data[2] << 8 | data[3]);
 		req = (data[2] << 8 | data[3]);
@@ -71,10 +74,14 @@ static int isight_firmware_load(struct usb_interface *intf,
 			continue;
 			continue;
 
 
 		for (; len > 0; req += 50) {
 		for (; len > 0; req += 50) {
-			llen = len > 50 ? 50 : len;
+			llen = min(len, 50);
 			len -= llen;
 			len -= llen;
-
-			buf = kmalloc(llen, GFP_KERNEL);
+			if (ptr+llen > firmware->data+firmware->size) {
+				printk(KERN_ERR
+				       "Malformed isight firmware");
+				ret = -ENODEV;
+				goto out;
+			}
 			memcpy(buf, ptr, llen);
 			memcpy(buf, ptr, llen);
 
 
 			ptr += llen;
 			ptr += llen;
@@ -89,16 +96,18 @@ static int isight_firmware_load(struct usb_interface *intf,
 				goto out;
 				goto out;
 			}
 			}
 
 
-			kfree(buf);
 		}
 		}
 	}
 	}
+
 	if (usb_control_msg
 	if (usb_control_msg
 	    (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1,
 	    (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1,
 	     300) != 1) {
 	     300) != 1) {
 		printk(KERN_ERR "isight firmware loading completion failed\n");
 		printk(KERN_ERR "isight firmware loading completion failed\n");
 		ret = -ENODEV;
 		ret = -ENODEV;
 	}
 	}
+
 out:
 out:
+	kfree(buf);
 	release_firmware(firmware);
 	release_firmware(firmware);
 	return ret;
 	return ret;
 }
 }