Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: dummy-hcd: Fix failure to give back unlinked URBs

The syzkaller USB fuzzer identified a failure mode in which dummy-hcd
would never give back an unlinked URB. This causes usb_kill_urb() to
hang, leading to WARNINGs and unkillable threads.

In dummy-hcd, all URBs are given back by the dummy_timer() routine as
it scans through the list of pending URBS. Failure to give back URBs
can be caused by failure to start or early exit from the scanning
loop. The code currently has two such pathways: One is triggered when
an unsupported bus transfer speed is encountered, and the other by
exhausting the simulated bandwidth for USB transfers during a frame.

This patch removes those two paths, thereby allowing all unlinked URBs
to be given back in a timely manner. It adds a check for the bus
speed when the gadget first starts running, so that dummy_timer() will
never thereafter encounter an unsupported speed. And it prevents the
loop from exiting as soon as the total bandwidth has been used up (the
scanning loop continues, giving back unlinked URBs as they are found,
but not transferring any more data).

Thanks to Andrey Konovalov for manually running the syzkaller fuzzer
to help track down the source of the bug.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Reported-and-tested-by: syzbot+d919b0f29d7b5a4994b9@syzkaller.appspotmail.com
CC: <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Alan Stern and committed by
Greg Kroah-Hartman
fc834e60 c01c348e

+15 -4
+15 -4
drivers/usb/gadget/udc/dummy_hcd.c
··· 979 979 struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(g); 980 980 struct dummy *dum = dum_hcd->dum; 981 981 982 - if (driver->max_speed == USB_SPEED_UNKNOWN) 982 + switch (g->speed) { 983 + /* All the speeds we support */ 984 + case USB_SPEED_LOW: 985 + case USB_SPEED_FULL: 986 + case USB_SPEED_HIGH: 987 + case USB_SPEED_SUPER: 988 + break; 989 + default: 990 + dev_err(dummy_dev(dum_hcd), "Unsupported driver max speed %d\n", 991 + driver->max_speed); 983 992 return -EINVAL; 993 + } 984 994 985 995 /* 986 996 * SLAVE side init ... the layer above hardware, which ··· 1794 1784 /* Bus speed is 500000 bytes/ms, so use a little less */ 1795 1785 total = 490000; 1796 1786 break; 1797 - default: 1787 + default: /* Can't happen */ 1798 1788 dev_err(dummy_dev(dum_hcd), "bogus device speed\n"); 1799 - return; 1789 + total = 0; 1790 + break; 1800 1791 } 1801 1792 1802 1793 /* FIXME if HZ != 1000 this will probably misbehave ... */ ··· 1839 1828 1840 1829 /* Used up this frame's bandwidth? */ 1841 1830 if (total <= 0) 1842 - break; 1831 + continue; 1843 1832 1844 1833 /* find the gadget's ep for this request (if configured) */ 1845 1834 address = usb_pipeendpoint (urb->pipe);