diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2020-05-01 23:07:28 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-05-27 18:46:34 +0300 |
commit | c8d323578e36d3b94b41c1bd2093bcf86dd7d754 (patch) | |
tree | 7f6ef179ca0c3873e40f3788572e28ad16d16c4f /drivers/usb | |
parent | 42b32a43529eb07f1e53ac987a027c3dbb6adb45 (diff) | |
download | linux-c8d323578e36d3b94b41c1bd2093bcf86dd7d754.tar.xz |
USB: core: Fix misleading driver bug report
[ Upstream commit ac854131d9844f79e2fdcef67a7707227538d78a ]
The syzbot fuzzer found a race between URB submission to endpoint 0
and device reset. Namely, during the reset we call usb_ep0_reinit()
because the characteristics of ep0 may have changed (if the reset
follows a firmware update, for example). While usb_ep0_reinit() is
running there is a brief period during which the pointers stored in
udev->ep_in[0] and udev->ep_out[0] are set to NULL, and if an URB is
submitted to ep0 during that period, usb_urb_ep_type_check() will
report it as a driver bug. In the absence of those pointers, the
routine thinks that the endpoint doesn't exist. The log message looks
like this:
------------[ cut here ]------------
usb 2-1: BOGUS urb xfer, pipe 2 != type 2
WARNING: CPU: 0 PID: 9241 at drivers/usb/core/urb.c:478
usb_submit_urb+0x1188/0x1460 drivers/usb/core/urb.c:478
Now, although submitting an URB while the device is being reset is a
questionable thing to do, it shouldn't count as a driver bug as severe
as submitting an URB for an endpoint that doesn't exist. Indeed,
endpoint 0 always exists, even while the device is in its unconfigured
state.
To prevent these misleading driver bug reports, this patch updates
usb_disable_endpoint() to avoid clearing the ep_in[] and ep_out[]
pointers when the endpoint being disabled is ep0. There's no danger
of leaving a stale pointer in place, because the usb_host_endpoint
structure being pointed to is stored permanently in udev->ep0; it
doesn't get deallocated until the entire usb_device structure does.
Reported-and-tested-by: syzbot+db339689b2101f6f6071@syzkaller.appspotmail.com
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.2005011558590.903-100000@netrider.rowland.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/message.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 02eaac7e1e34..a1ac2f0723b0 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1143,11 +1143,11 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr, if (usb_endpoint_out(epaddr)) { ep = dev->ep_out[epnum]; - if (reset_hardware) + if (reset_hardware && epnum != 0) dev->ep_out[epnum] = NULL; } else { ep = dev->ep_in[epnum]; - if (reset_hardware) + if (reset_hardware && epnum != 0) dev->ep_in[epnum] = NULL; } if (ep) { |