ChangeSet 1.911, 2002/11/20 00:10:26-08:00, zwane@holomorphy.com [PATCH] USB core/config.c == memory corruption parse_interface allocates the incorrect storage size for additional altsettings (new buffer) leading to a BUG being triggered in mm/slab.c:1453 when we do the memcpy from the old buffer to the new buffer (writing beyond new buffer). Patch appended, tested with an OV511 on an Intel PIIX4 diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c --- a/drivers/usb/core/config.c Wed Nov 20 01:00:47 2002 +++ b/drivers/usb/core/config.c Wed Nov 20 01:00:47 2002 @@ -109,7 +109,8 @@ interface->num_altsetting = 0; interface->max_altsetting = USB_ALTSETTINGALLOC; - interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL); + interface->altsetting = kmalloc(sizeof(*interface->altsetting) * interface->max_altsetting, + GFP_KERNEL); if (!interface->altsetting) { err("couldn't kmalloc interface->altsetting"); @@ -118,29 +119,27 @@ while (size > 0) { struct usb_interface_descriptor *d; - + if (interface->num_altsetting >= interface->max_altsetting) { - void *ptr; + struct usb_host_interface *ptr; int oldmas; oldmas = interface->max_altsetting; interface->max_altsetting += USB_ALTSETTINGALLOC; if (interface->max_altsetting > USB_MAXALTSETTING) { - warn("too many alternate settings (max %d)", - USB_MAXALTSETTING); + warn("too many alternate settings (incr %d max %d)\n", + USB_ALTSETTINGALLOC, USB_MAXALTSETTING); return -1; } - ptr = interface->altsetting; - interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL); - if (!interface->altsetting) { + ptr = kmalloc(sizeof(*ptr) * interface->max_altsetting, GFP_KERNEL); + if (ptr == NULL) { err("couldn't kmalloc interface->altsetting"); - interface->altsetting = ptr; return -1; } - memcpy(interface->altsetting, ptr, sizeof(struct usb_interface_descriptor) * oldmas); - - kfree(ptr); + memcpy(ptr, interface->altsetting, sizeof(*interface->altsetting) * oldmas); + kfree(interface->altsetting); + interface->altsetting = ptr; } ifp = interface->altsetting + interface->num_altsetting;