From 90a646c770c50cc206ceba0d7b50453c46c13c36 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 1 Oct 2014 11:29:14 +0200 Subject: [PATCH] usb: Do not allow usb_alloc_streams on unconfigured devices This commit fixes the following oops: [10238.622067] scsi host3: uas_eh_bus_reset_handler start [10240.766164] usb 3-4: reset SuperSpeed USB device number 3 using xhci_hcd [10245.779365] usb 3-4: device descriptor read/8, error -110 [10245.883331] usb 3-4: reset SuperSpeed USB device number 3 using xhci_hcd [10250.897603] usb 3-4: device descriptor read/8, error -110 [10251.058200] BUG: unable to handle kernel NULL pointer dereference at 0000000000000040 [10251.058244] IP: [] xhci_check_streams_endpoint+0x91/0x140 [10251.059473] Call Trace: [10251.059487] [] xhci_calculate_streams_and_bitmask+0xbc/0x130 [10251.059520] [] xhci_alloc_streams+0x10f/0x5a0 [10251.059548] [] ? check_preempt_curr+0x75/0xa0 [10251.059575] [] ? ttwu_do_wakeup+0x2c/0x100 [10251.059601] [] ? ttwu_do_activate.constprop.111+0x66/0x70 [10251.059635] [] usb_alloc_streams+0xab/0xf0 [10251.059662] [] uas_configure_endpoints+0x128/0x150 [uas] [10251.059694] [] uas_post_reset+0x3c/0xb0 [uas] [10251.059722] [] usb_reset_device+0x1b9/0x2a0 [10251.059749] [] uas_eh_bus_reset_handler+0xb2/0x190 [uas] [10251.059781] [] scsi_try_bus_reset+0x53/0x110 [10251.059808] [] scsi_eh_bus_reset+0xf7/0x270 The problem is the following call sequence (simplified): 1) usb_reset_device 2) usb_reset_and_verify_device 2) hub_port_init 3) hub_port_finish_reset 3) xhci_discover_or_reset_device This frees xhci->devs[slot_id]->eps[ep_index].ring for all eps but 0 4) usb_get_device_descriptor This fails 5) hub_port_init fails 6) usb_reset_and_verify_device fails, does not restore device config 7) uas_post_reset 8) xhci_alloc_streams NULL deref on the free-ed ring This commit fixes this by not allowing usb_alloc_streams to continue if the device is not configured. Note that we do allow usb_free_streams to continue after a (logical) disconnect, as it is necessary to explicitly free the streams at the xhci controller level. Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index b84fb141e122..a6efb4184f2b 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2060,6 +2060,8 @@ int usb_alloc_streams(struct usb_interface *interface, return -EINVAL; if (dev->speed != USB_SPEED_SUPER) return -EINVAL; + if (dev->state < USB_STATE_CONFIGURED) + return -ENODEV; for (i = 0; i < num_eps; i++) { /* Streams only apply to bulk endpoints. */