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>

authored by Matthew Garrett and committed by Greg Kroah-Hartman 62b58848 6460a261

+16 -7
+16 -7
drivers/usb/misc/isight_firmware.c
··· 39 struct usb_device *dev = interface_to_usbdev(intf); 40 int llen, len, req, ret = 0; 41 const struct firmware *firmware; 42 - unsigned char *buf; 43 unsigned char data[4]; 44 - char *ptr; 45 46 if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) { 47 printk(KERN_ERR "Unable to load isight firmware\n"); ··· 62 goto out; 63 } 64 65 - while (1) { 66 memcpy(data, ptr, 4); 67 len = (data[0] << 8 | data[1]); 68 req = (data[2] << 8 | data[3]); ··· 74 continue; 75 76 for (; len > 0; req += 50) { 77 - llen = len > 50 ? 50 : len; 78 len -= llen; 79 - 80 - buf = kmalloc(llen, GFP_KERNEL); 81 memcpy(buf, ptr, llen); 82 83 ptr += llen; ··· 96 goto out; 97 } 98 99 - kfree(buf); 100 } 101 } 102 if (usb_control_msg 103 (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1, 104 300) != 1) { 105 printk(KERN_ERR "isight firmware loading completion failed\n"); 106 ret = -ENODEV; 107 } 108 out: 109 release_firmware(firmware); 110 return ret; 111 }
··· 39 struct usb_device *dev = interface_to_usbdev(intf); 40 int llen, len, req, ret = 0; 41 const struct firmware *firmware; 42 + unsigned char *buf = kmalloc(50, GFP_KERNEL); 43 unsigned char data[4]; 44 + u8 *ptr; 45 + 46 + if (!buf) 47 + return -ENOMEM; 48 49 if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) { 50 printk(KERN_ERR "Unable to load isight firmware\n"); ··· 59 goto out; 60 } 61 62 + while (ptr+4 <= firmware->data+firmware->size) { 63 memcpy(data, ptr, 4); 64 len = (data[0] << 8 | data[1]); 65 req = (data[2] << 8 | data[3]); ··· 71 continue; 72 73 for (; len > 0; req += 50) { 74 + llen = min(len, 50); 75 len -= llen; 76 + if (ptr+llen > firmware->data+firmware->size) { 77 + printk(KERN_ERR 78 + "Malformed isight firmware"); 79 + ret = -ENODEV; 80 + goto out; 81 + } 82 memcpy(buf, ptr, llen); 83 84 ptr += llen; ··· 89 goto out; 90 } 91 92 } 93 } 94 + 95 if (usb_control_msg 96 (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1, 97 300) != 1) { 98 printk(KERN_ERR "isight firmware loading completion failed\n"); 99 ret = -ENODEV; 100 } 101 + 102 out: 103 + kfree(buf); 104 release_firmware(firmware); 105 return ret; 106 }