diff mbox series

[3/5] usb: xhci: avoid null pointer deref when bos field is NULL

Message ID 1558524841-25397-4-git-send-email-mathias.nyman@linux.intel.com (mailing list archive)
State Superseded
Commit 7aa1bb2ffd84d6b9b5f546b079bb15cd0ab6e76e
Headers show
Series xhci fixes for usb-linus | expand

Commit Message

Mathias Nyman May 22, 2019, 11:33 a.m. UTC
From: Carsten Schmid <carsten_schmid@mentor.com>

With defective USB sticks we see the following error happen:
usb 1-3: new high-speed USB device number 6 using xhci_hcd
usb 1-3: device descriptor read/64, error -71
usb 1-3: device descriptor read/64, error -71
usb 1-3: new high-speed USB device number 7 using xhci_hcd
usb 1-3: device descriptor read/64, error -71
usb 1-3: unable to get BOS descriptor set
usb 1-3: New USB device found, idVendor=0781, idProduct=5581
usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
...
BUG: unable to handle kernel NULL pointer dereference at 0000000000000008

This comes from the following place:
[ 1660.215380] IP: xhci_set_usb2_hardware_lpm+0xdf/0x3d0 [xhci_hcd]
[ 1660.222092] PGD 0 P4D 0
[ 1660.224918] Oops: 0000 [#1] PREEMPT SMP NOPTI
[ 1660.425520] CPU: 1 PID: 38 Comm: kworker/1:1 Tainted: P     U  W  O    4.14.67-apl #1
[ 1660.434277] Workqueue: usb_hub_wq hub_event [usbcore]
[ 1660.439918] task: ffffa295b6ae4c80 task.stack: ffffad4580150000
[ 1660.446532] RIP: 0010:xhci_set_usb2_hardware_lpm+0xdf/0x3d0 [xhci_hcd]
[ 1660.453821] RSP: 0018:ffffad4580153c70 EFLAGS: 00010046
[ 1660.459655] RAX: 0000000000000000 RBX: ffffa295b4d7c000 RCX: 0000000000000002
[ 1660.467625] RDX: 0000000000000002 RSI: ffffffff984a55b2 RDI: ffffffff984a55b2
[ 1660.475586] RBP: ffffad4580153cc8 R08: 0000000000d6520a R09: 0000000000000001
[ 1660.483556] R10: ffffad4580a004a0 R11: 0000000000000286 R12: ffffa295b4d7c000
[ 1660.491525] R13: 0000000000010648 R14: ffffa295a84e1800 R15: 0000000000000000
[ 1660.499494] FS:  0000000000000000(0000) GS:ffffa295bfc80000(0000) knlGS:0000000000000000
[ 1660.508530] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1660.514947] CR2: 0000000000000008 CR3: 000000025a114000 CR4: 00000000003406a0
[ 1660.522917] Call Trace:
[ 1660.525657]  usb_set_usb2_hardware_lpm+0x3d/0x70 [usbcore]
[ 1660.531792]  usb_disable_device+0x242/0x260 [usbcore]
[ 1660.537439]  usb_disconnect+0xc1/0x2b0 [usbcore]
[ 1660.542600]  hub_event+0x596/0x18f0 [usbcore]
[ 1660.547467]  ? trace_preempt_on+0xdf/0x100
[ 1660.552040]  ? process_one_work+0x1c1/0x410
[ 1660.556708]  process_one_work+0x1d2/0x410
[ 1660.561184]  ? preempt_count_add.part.3+0x21/0x60
[ 1660.566436]  worker_thread+0x2d/0x3f0
[ 1660.570522]  kthread+0x122/0x140
[ 1660.574123]  ? process_one_work+0x410/0x410
[ 1660.578792]  ? kthread_create_on_node+0x60/0x60
[ 1660.583849]  ret_from_fork+0x3a/0x50
[ 1660.587839] Code: 00 49 89 c3 49 8b 84 24 50 16 00 00 8d 4a ff 48 8d 04 c8 48 89 ca 4c 8b 10 45 8b 6a 04 48 8b 00 48 89 45 c0 49 8b 86 80 03 00 00 <48> 8b 40 08 8b 40 03 0f 1f 44 00 00 45 85 ff 0f 84 81 01 00 00
[ 1660.608980] RIP: xhci_set_usb2_hardware_lpm+0xdf/0x3d0 [xhci_hcd] RSP: ffffad4580153c70
[ 1660.617921] CR2: 0000000000000008

Tracking this down shows that udev->bos is NULL in the following code:
(xhci.c, in xhci_set_usb2_hardware_lpm)
	field = le32_to_cpu(udev->bos->ext_cap->bmAttributes);  <<<<<<< here

	xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n",
			enable ? "enable" : "disable", port_num + 1);

	if (enable) {
		/* Host supports BESL timeout instead of HIRD */
		if (udev->usb2_hw_lpm_besl_capable) {
			/* if device doesn't have a preferred BESL value use a
			 * default one which works with mixed HIRD and BESL
			 * systems. See XHCI_DEFAULT_BESL definition in xhci.h
			 */
			if ((field & USB_BESL_SUPPORT) &&
			    (field & USB_BESL_BASELINE_VALID))
				hird = USB_GET_BESL_BASELINE(field);
			else
				hird = udev->l1_params.besl;

The failing case is when disabling LPM. So it is sufficient to avoid
access to udev->bos by moving the instruction into the "enable" clause.

Cc: Stable <stable@vger.kernel.org>
Signed-off-by: Carsten Schmid <carsten_schmid@mentor.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
 drivers/usb/host/xhci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Schmid, Carsten June 3, 2019, 7:12 a.m. UTC | #1
Hi Sasha,

i was OOO last week.
Let me check why the patch doesn't apply in the older kernel series.
I originally developed it on a 4.14.86 and ported it to 5.1.

Shouldn't be a big problem, its a "one line mover" only.

BR
Carsten


> -----Ursprüngliche Nachricht-----
> Von: Sasha Levin [mailto:sashal@kernel.org]
> Gesendet: Mittwoch, 29. Mai 2019 15:15
> An: Sasha Levin <sashal@kernel.org>; Mathias Nyman
> <mathias.nyman@linux.intel.com>; Schmid, Carsten
> <Carsten_Schmid@mentor.com>; gregkh@linuxfoundation.org
> Cc: linux-usb@vger.kernel.org; Stable <stable@vger.kernel.org>;
> stable@vger.kernel.org
> Betreff: Re: [PATCH 3/5] usb: xhci: avoid null pointer deref when bos field is
> NULL
> 
> Hi,
> 
> [This is an automated email]
> 
> This commit has been processed because it contains a -stable tag.
> The stable tag indicates that it's relevant for the following trees: all
> 
> The bot has tested the following trees: v5.1.4, v5.0.18, v4.19.45, v4.14.121,
> v4.9.178, v4.4.180, v3.18.140.
> 
> v5.1.4: Build OK!
> v5.0.18: Build OK!
> v4.19.45: Build OK!
> v4.14.121: Failed to apply! Possible dependencies:
>     01451ad47e272 ("powerpc/powermac: Use setup_timer() helper")
>     38986ffa6a748 ("xhci: use port structures instead of port arrays in xhci.c
> functions")
>     83ad1e6a1dc04 ("powerpc/oprofile: Use setup_timer() helper")
>     8d6b1bf20f61c ("powerpc/6xx: Use setup_timer() helper")
>     b1fc2839d2f92 ("drm/msm: Implement preemption for A5XX targets")
>     b9eaf18722221 ("treewide: init_timer() -> setup_timer()")
>     cd414f3d93168 ("drm/msm: Move memptrs to msm_gpu")
>     e629cfa36ea08 ("MIPS: Lasat: Use setup_timer() helper")
>     e99e88a9d2b06 ("treewide: setup_timer() -> timer_setup()")
>     eec874ce5ff1f ("drm/msm/adreno: load gpu at probe/bind time")
>     f7de15450e906 ("drm/msm: Add per-instance submit queues")
>     f97decac5f4c2 ("drm/msm: Support multiple ringbuffers")
> 
> v4.9.178: Failed to apply! Possible dependencies:
>     01451ad47e272 ("powerpc/powermac: Use setup_timer() helper")
>     38986ffa6a748 ("xhci: use port structures instead of port arrays in xhci.c
> functions")
>     53460c53b7619 ("[media] au0828: Add timer to restart TS stream if no data
> arrives on bulk endpoint")
>     7c96f59e0cafe ("[media] s5p-mfc: Fix initialization of internal structures")
>     83ad1e6a1dc04 ("powerpc/oprofile: Use setup_timer() helper")
>     8d6b1bf20f61c ("powerpc/6xx: Use setup_timer() helper")
>     b9eaf18722221 ("treewide: init_timer() -> setup_timer()")
>     cf43e6be865a5 ("block: add scalable completion tracking of requests")
>     e629cfa36ea08 ("MIPS: Lasat: Use setup_timer() helper")
>     e806402130c9c ("block: split out request-only flags into a new namespace")
>     e99e88a9d2b06 ("treewide: setup_timer() -> timer_setup()")
> 
> v4.4.180: Failed to apply! Possible dependencies:
>     01451ad47e272 ("powerpc/powermac: Use setup_timer() helper")
>     37f895d7e85e7 ("NFC: pn533: Fix socket deadlock")
>     38986ffa6a748 ("xhci: use port structures instead of port arrays in xhci.c
> functions")
>     53460c53b7619 ("[media] au0828: Add timer to restart TS stream if no data
> arrives on bulk endpoint")
>     7c96f59e0cafe ("[media] s5p-mfc: Fix initialization of internal structures")
>     80c1bce9aa315 ("[media] au0828: Refactoring for start_urb_transfer()")
>     83ad1e6a1dc04 ("powerpc/oprofile: Use setup_timer() helper")
>     8d6b1bf20f61c ("powerpc/6xx: Use setup_timer() helper")
>     9815c7cf22dac ("NFC: pn533: Separate physical layer from the core
> implementation")
>     b9eaf18722221 ("treewide: init_timer() -> setup_timer()")
>     e629cfa36ea08 ("MIPS: Lasat: Use setup_timer() helper")
>     e997ebbe46fe4 ("NFC: pn533: Send ATR_REQ only if
> NFC_PROTO_NFC_DEP bit is set")
>     e99e88a9d2b06 ("treewide: setup_timer() -> timer_setup()")
> 
> v3.18.140: Failed to apply! Possible dependencies:
>     0a5942c8e1480 ("NFC: Add ACPI support for NXP PN544")
>     34ac49664149d ("NFC: nci: remove current SLEEP mode management")
>     3590ebc040c9e ("NFC: logging neatening")
>     3682f49f32051 ("NFC: netlink: Add new netlink command
> NFC_CMD_ACTIVATE_TARGET")
>     37f895d7e85e7 ("NFC: pn533: Fix socket deadlock")
>     38986ffa6a748 ("xhci: use port structures instead of port arrays in xhci.c
> functions")
>     53460c53b7619 ("[media] au0828: Add timer to restart TS stream if no data
> arrives on bulk endpoint")
>     5df848f37b1d2 ("NFC: pn533: fix error return code")
>     7c96f59e0cafe ("[media] s5p-mfc: Fix initialization of internal structures")
>     80c1bce9aa315 ("[media] au0828: Refactoring for start_urb_transfer()")
>     9295b5b569fc4 ("NFC: nci: Add support for different
> NCI_DEACTIVATE_TYPE")
>     96d4581f0b371 ("NFC: netlink: Add mode parameter to deactivate_target
> functions")
>     9815c7cf22dac ("NFC: pn533: Separate physical layer from the core
> implementation")
>     b9eaf18722221 ("treewide: init_timer() -> setup_timer()")
>     d7979e130ebb0 ("NFC: NCI: Signal deactivation in Target mode")
>     e997ebbe46fe4 ("NFC: pn533: Send ATR_REQ only if
> NFC_PROTO_NFC_DEP bit is set")
>     e99e88a9d2b06 ("treewide: setup_timer() -> timer_setup()")
> 
> 
> How should we proceed with this patch?
> 
> --
> Thanks,
> Sasha
diff mbox series

Patch

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index a9bb796..048a675 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4320,7 +4320,6 @@  static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
 	pm_addr = ports[port_num]->addr + PORTPMSC;
 	pm_val = readl(pm_addr);
 	hlpm_addr = ports[port_num]->addr + PORTHLPMC;
-	field = le32_to_cpu(udev->bos->ext_cap->bmAttributes);
 
 	xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n",
 			enable ? "enable" : "disable", port_num + 1);
@@ -4332,6 +4331,7 @@  static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
 			 * default one which works with mixed HIRD and BESL
 			 * systems. See XHCI_DEFAULT_BESL definition in xhci.h
 			 */
+			field = le32_to_cpu(udev->bos->ext_cap->bmAttributes);
 			if ((field & USB_BESL_SUPPORT) &&
 			    (field & USB_BESL_BASELINE_VALID))
 				hird = USB_GET_BESL_BASELINE(field);