summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorMatthew Garrett <mjg59@srcf.ucam.org>2008-06-06 12:35:15 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2008-06-11 17:06:33 -0700
commit62b5884875fcd4babf6c0c377046f226abbfe491 (patch)
treee0aa7d2f40ef390403bfc7258199fe7b7cca399b /drivers/usb
parent6460a261b5893e769a314c246faec31bbc4aad9c (diff)
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>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/misc/isight_firmware.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c
index 390e0488553..9f30aa1f8a5 100644
--- a/drivers/usb/misc/isight_firmware.c
+++ b/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);
int llen, len, req, ret = 0;
const struct firmware *firmware;
- unsigned char *buf;
+ unsigned char *buf = kmalloc(50, GFP_KERNEL);
unsigned char data[4];
- char *ptr;
+ u8 *ptr;
+
+ if (!buf)
+ return -ENOMEM;
if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) {
printk(KERN_ERR "Unable to load isight firmware\n");
@@ -59,7 +62,7 @@ static int isight_firmware_load(struct usb_interface *intf,
goto out;
}
- while (1) {
+ while (ptr+4 <= firmware->data+firmware->size) {
memcpy(data, ptr, 4);
len = (data[0] << 8 | data[1]);
req = (data[2] << 8 | data[3]);
@@ -71,10 +74,14 @@ static int isight_firmware_load(struct usb_interface *intf,
continue;
for (; len > 0; req += 50) {
- llen = len > 50 ? 50 : len;
+ llen = min(len, 50);
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);
ptr += llen;
@@ -89,16 +96,18 @@ static int isight_firmware_load(struct usb_interface *intf,
goto out;
}
- kfree(buf);
}
}
+
if (usb_control_msg
(dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1,
300) != 1) {
printk(KERN_ERR "isight firmware loading completion failed\n");
ret = -ENODEV;
}
+
out:
+ kfree(buf);
release_firmware(firmware);
return ret;
}