]>
Commit | Line | Data |
---|---|---|
14e9555d GKH |
1 | From 7aa1bb2ffd84d6b9b5f546b079bb15cd0ab6e76e Mon Sep 17 00:00:00 2001 |
2 | From: Carsten Schmid <carsten_schmid@mentor.com> | |
3 | Date: Wed, 22 May 2019 14:33:59 +0300 | |
4 | Subject: usb: xhci: avoid null pointer deref when bos field is NULL | |
5 | ||
6 | From: Carsten Schmid <carsten_schmid@mentor.com> | |
7 | ||
8 | commit 7aa1bb2ffd84d6b9b5f546b079bb15cd0ab6e76e upstream. | |
9 | ||
10 | With defective USB sticks we see the following error happen: | |
11 | usb 1-3: new high-speed USB device number 6 using xhci_hcd | |
12 | usb 1-3: device descriptor read/64, error -71 | |
13 | usb 1-3: device descriptor read/64, error -71 | |
14 | usb 1-3: new high-speed USB device number 7 using xhci_hcd | |
15 | usb 1-3: device descriptor read/64, error -71 | |
16 | usb 1-3: unable to get BOS descriptor set | |
17 | usb 1-3: New USB device found, idVendor=0781, idProduct=5581 | |
18 | usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3 | |
19 | ... | |
20 | BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 | |
21 | ||
22 | This comes from the following place: | |
23 | [ 1660.215380] IP: xhci_set_usb2_hardware_lpm+0xdf/0x3d0 [xhci_hcd] | |
24 | [ 1660.222092] PGD 0 P4D 0 | |
25 | [ 1660.224918] Oops: 0000 [#1] PREEMPT SMP NOPTI | |
26 | [ 1660.425520] CPU: 1 PID: 38 Comm: kworker/1:1 Tainted: P U W O 4.14.67-apl #1 | |
27 | [ 1660.434277] Workqueue: usb_hub_wq hub_event [usbcore] | |
28 | [ 1660.439918] task: ffffa295b6ae4c80 task.stack: ffffad4580150000 | |
29 | [ 1660.446532] RIP: 0010:xhci_set_usb2_hardware_lpm+0xdf/0x3d0 [xhci_hcd] | |
30 | [ 1660.453821] RSP: 0018:ffffad4580153c70 EFLAGS: 00010046 | |
31 | [ 1660.459655] RAX: 0000000000000000 RBX: ffffa295b4d7c000 RCX: 0000000000000002 | |
32 | [ 1660.467625] RDX: 0000000000000002 RSI: ffffffff984a55b2 RDI: ffffffff984a55b2 | |
33 | [ 1660.475586] RBP: ffffad4580153cc8 R08: 0000000000d6520a R09: 0000000000000001 | |
34 | [ 1660.483556] R10: ffffad4580a004a0 R11: 0000000000000286 R12: ffffa295b4d7c000 | |
35 | [ 1660.491525] R13: 0000000000010648 R14: ffffa295a84e1800 R15: 0000000000000000 | |
36 | [ 1660.499494] FS: 0000000000000000(0000) GS:ffffa295bfc80000(0000) knlGS:0000000000000000 | |
37 | [ 1660.508530] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 | |
38 | [ 1660.514947] CR2: 0000000000000008 CR3: 000000025a114000 CR4: 00000000003406a0 | |
39 | [ 1660.522917] Call Trace: | |
40 | [ 1660.525657] usb_set_usb2_hardware_lpm+0x3d/0x70 [usbcore] | |
41 | [ 1660.531792] usb_disable_device+0x242/0x260 [usbcore] | |
42 | [ 1660.537439] usb_disconnect+0xc1/0x2b0 [usbcore] | |
43 | [ 1660.542600] hub_event+0x596/0x18f0 [usbcore] | |
44 | [ 1660.547467] ? trace_preempt_on+0xdf/0x100 | |
45 | [ 1660.552040] ? process_one_work+0x1c1/0x410 | |
46 | [ 1660.556708] process_one_work+0x1d2/0x410 | |
47 | [ 1660.561184] ? preempt_count_add.part.3+0x21/0x60 | |
48 | [ 1660.566436] worker_thread+0x2d/0x3f0 | |
49 | [ 1660.570522] kthread+0x122/0x140 | |
50 | [ 1660.574123] ? process_one_work+0x410/0x410 | |
51 | [ 1660.578792] ? kthread_create_on_node+0x60/0x60 | |
52 | [ 1660.583849] ret_from_fork+0x3a/0x50 | |
53 | [ 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 | |
54 | [ 1660.608980] RIP: xhci_set_usb2_hardware_lpm+0xdf/0x3d0 [xhci_hcd] RSP: ffffad4580153c70 | |
55 | [ 1660.617921] CR2: 0000000000000008 | |
56 | ||
57 | Tracking this down shows that udev->bos is NULL in the following code: | |
58 | (xhci.c, in xhci_set_usb2_hardware_lpm) | |
59 | field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); <<<<<<< here | |
60 | ||
61 | xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n", | |
62 | enable ? "enable" : "disable", port_num + 1); | |
63 | ||
64 | if (enable) { | |
65 | /* Host supports BESL timeout instead of HIRD */ | |
66 | if (udev->usb2_hw_lpm_besl_capable) { | |
67 | /* if device doesn't have a preferred BESL value use a | |
68 | * default one which works with mixed HIRD and BESL | |
69 | * systems. See XHCI_DEFAULT_BESL definition in xhci.h | |
70 | */ | |
71 | if ((field & USB_BESL_SUPPORT) && | |
72 | (field & USB_BESL_BASELINE_VALID)) | |
73 | hird = USB_GET_BESL_BASELINE(field); | |
74 | else | |
75 | hird = udev->l1_params.besl; | |
76 | ||
77 | The failing case is when disabling LPM. So it is sufficient to avoid | |
78 | access to udev->bos by moving the instruction into the "enable" clause. | |
79 | ||
80 | Cc: Stable <stable@vger.kernel.org> | |
81 | Signed-off-by: Carsten Schmid <carsten_schmid@mentor.com> | |
82 | Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> | |
83 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
84 | ||
85 | --- | |
86 | drivers/usb/host/xhci.c | 2 +- | |
87 | 1 file changed, 1 insertion(+), 1 deletion(-) | |
88 | ||
89 | --- a/drivers/usb/host/xhci.c | |
90 | +++ b/drivers/usb/host/xhci.c | |
91 | @@ -4287,7 +4287,6 @@ static int xhci_set_usb2_hardware_lpm(st | |
92 | pm_addr = ports[port_num]->addr + PORTPMSC; | |
93 | pm_val = readl(pm_addr); | |
94 | hlpm_addr = ports[port_num]->addr + PORTHLPMC; | |
95 | - field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); | |
96 | ||
97 | xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n", | |
98 | enable ? "enable" : "disable", port_num + 1); | |
99 | @@ -4299,6 +4298,7 @@ static int xhci_set_usb2_hardware_lpm(st | |
100 | * default one which works with mixed HIRD and BESL | |
101 | * systems. See XHCI_DEFAULT_BESL definition in xhci.h | |
102 | */ | |
103 | + field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); | |
104 | if ((field & USB_BESL_SUPPORT) && | |
105 | (field & USB_BESL_BASELINE_VALID)) | |
106 | hird = USB_GET_BESL_BASELINE(field); |