Dmitry, Attached are the patches Anirudh created. Also, I have added him to the thread if you have any questions or comments for him. Rosie On Thu Jul 28 2016 16:58:27 GMT-0400 (EDT), roswest wrote: > Dmitry, > > Tomorrow is his last day, but he is going to try to accomplish that. > > Rosie > > On Thu Jul 28 2016 13:48:48 GMT-0400 (EDT), Dmitry Torokhov wrote: >> Hi Rosie, >> >> On Thu, Jul 28, 2016 at 12:23:09PM -0400, roswest wrote: >>> >>> Dmitry, >>> >>> Hi, I am an engineer at Cisco Systems, and this summer we tasked some >>> interns with performing USB fuzzing. One of the interns, Anirudh Bagde, >>> was able to crash the USB stack due to an error in the iforce module and >>> discovered a buffer over-read in the usbtouchscreen module. Please see >>> the attachment for details. >> >> Thank you for the report. Any chance Anirudh could provide patches to >> fix these issues as well? >> >> Thanks! >> >
--- a/drivers/input/joystick/iforce/iforce-usb.c 2016-07-29 15:02:47.602630504 -0400 +++ b/drivers/input/joystick/iforce/iforce-usb.c 2016-07-29 15:02:32.946812336 -0400 @@ -135,12 +135,23 @@ { struct usb_device *dev = interface_to_usbdev(intf); struct usb_host_interface *interface; - struct usb_endpoint_descriptor *epirq, *epout; + struct usb_endpoint_descriptor *epirq = NULL, *epout = NULL; struct iforce *iforce; - int err = -ENOMEM; + int i, err = -ENOMEM; interface = intf->cur_altsetting; + for (i = 0; i < interface->desc.bNumEndpoints; i++) { + if (!epirq && + usb_endpoint_dir_in(&interface->endpoint[i].desc)) + epirq = &interface->endpoint[i].desc; + if (!epout && + usb_endpoint_dir_out(&interface->endpoint[i].desc)) + epout = &interface->endpoint[i].desc; + } + if (!epirq || !epout) + return -ENODEV; + epirq = &interface->endpoint[0].desc; epout = &interface->endpoint[1].desc;
--- a/drivers/input/touchscreen/usbtouchscreen.c 2016-07-29 17:33:31.430429835 -0400 +++ b/drivers/input/touchscreen/usbtouchscreen.c 2016-07-29 17:31:57.795591496 -0400 @@ -85,7 +85,8 @@ */ bool irq_always; - void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); + void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, + unsigned int len); /* * used to get the packet len. possible return values: @@ -95,7 +96,8 @@ */ int (*get_pkt_len) (unsigned char *pkt, int len); - int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt); + int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt, + unsigned int len); int (*alloc) (struct usbtouch_usb *usbtouch); int (*init) (struct usbtouch_usb *usbtouch); void (*exit) (struct usbtouch_usb *usbtouch); @@ -275,7 +277,8 @@ return ret; } -static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { int tmp = (pkt[0] << 8) | pkt[1]; dev->x = (pkt[2] << 8) | pkt[3]; @@ -343,7 +346,8 @@ return ret; } -static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) return 0; @@ -387,7 +391,8 @@ #define ETOUCH_PKT_TYPE_REPT2 0xB0 #define ETOUCH_PKT_TYPE_DIAG 0x0A -static int etouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int etouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { if ((pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT && (pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT2) @@ -422,7 +427,8 @@ * PanJit Part */ #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT -static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; @@ -442,7 +448,8 @@ #define MTOUCHUSB_RESET 7 #define MTOUCHUSB_REQ_CTRLLR_ID 10 -static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { if (hwcalib_xy) { dev->x = (pkt[4] << 8) | pkt[3]; @@ -501,7 +508,8 @@ * ITM Part */ #ifdef CONFIG_TOUCHSCREEN_USB_ITM -static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { int touch; /* @@ -538,7 +546,8 @@ #ifndef MULTI_PACKET #define MULTI_PACKET #endif -static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { unsigned int shift; @@ -569,7 +578,8 @@ * Gunze part */ #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE -static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80)) return 0; @@ -655,7 +665,8 @@ } -static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { dev->x = ((pkt[2] & 0x03) << 8) | pkt[1]; dev->y = ((pkt[4] & 0x03) << 8) | pkt[3]; @@ -670,7 +681,8 @@ * IRTOUCH Part */ #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH -static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { dev->x = (pkt[3] << 8) | pkt[2]; dev->y = (pkt[5] << 8) | pkt[4]; @@ -684,7 +696,8 @@ * ET&T TC5UH/TC4UM part */ #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB -static int tc45usb_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int tc45usb_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; @@ -710,7 +723,8 @@ return 0; } -static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { switch (pkt[0] & 0x98) { case 0x88: @@ -737,7 +751,8 @@ * General Touch Part */ #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH -static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { dev->x = (pkt[2] << 8) | pkt[1]; dev->y = (pkt[4] << 8) | pkt[3]; @@ -752,7 +767,8 @@ * GoTop Part */ #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP -static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; @@ -766,7 +782,8 @@ * JASTEC Part */ #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC -static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { dev->x = ((pkt[0] & 0x3f) << 6) | (pkt[2] & 0x3f); dev->y = ((pkt[1] & 0x3f) << 6) | (pkt[3] & 0x3f); @@ -780,7 +797,8 @@ * Zytronic Part */ #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC -static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { struct usb_interface *intf = dev->interface; @@ -964,7 +982,8 @@ kfree(priv); } -static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) +static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt, + unsigned int len) { struct nexio_touch_packet *packet = (void *) pkt; struct nexio_priv *priv = usbtouch->priv; @@ -977,6 +996,11 @@ if ((pkt[0] & 0xe0) != 0xe0) return 0; + if (data_len > len) + data_len = len; + if (x_len + y_len > data_len) + return 0; + if (data_len > 0xff) data_len -= 0x100; if (x_len > 0xff) @@ -1055,7 +1079,8 @@ #ifdef CONFIG_TOUCHSCREEN_USB_ELO -static int elo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +static int elo_read_data(struct usbtouch_usb *dev, unsigned char *pkt, + unsigned int len) { dev->x = (pkt[3] << 8) | pkt[2]; dev->y = (pkt[5] << 8) | pkt[4]; @@ -1072,7 +1097,7 @@ */ #ifdef MULTI_PACKET static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, - unsigned char *pkt, int len); + unsigned char *pkt, unsigned int len); #endif static struct usbtouch_device_info usbtouch_dev_info[] = { @@ -1303,11 +1328,11 @@ * Generic Part */ static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, - unsigned char *pkt, int len) + unsigned char *pkt, unsigned int len) { struct usbtouch_device_info *type = usbtouch->type; - if (!type->read_data(usbtouch, pkt)) + if (!type->read_data(usbtouch, pkt, len)) return; input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); @@ -1327,7 +1352,7 @@ #ifdef MULTI_PACKET static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, - unsigned char *pkt, int len) + unsigned char *pkt, unsigned int len) { unsigned char *buffer; int pkt_len, pos, buf_len, tmp;
Attachment:
signature.asc
Description: OpenPGP digital signature