diff options
| author | Zhengjun Xing <zhengjun.xing@linux.intel.com> | 2018-06-21 09:19:42 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-06-25 09:16:27 -0400 |
| commit | d850c1658328e757635a46763783c6fd56390dcb (patch) | |
| tree | 908b89e94206f043c9fd34792cdf069022a5d36f | |
| parent | 229bc19fd7aca4f37964af06e3583c1c8f36b5d6 (diff) | |
xhci: Fix kernel oops in trace_xhci_free_virt_device
commit 44a182b9d177 ("xhci: Fix use-after-free in xhci_free_virt_device")
set dev->udev pointer to NULL in xhci_free_dev(), it will cause kernel
panic in trace_xhci_free_virt_device. This patch reimplement the trace
function trace_xhci_free_virt_device, remove dev->udev dereference and
added more useful parameters to show in the trace function,it also makes
sure dev->udev is not NULL before calling trace_xhci_free_virt_device.
This issue happened when xhci-hcd trace is enabled and USB devices hot
plug test. Original use-after-free patch went to stable so this needs so
be applied there as well.
[ 1092.022457] usb 2-4: USB disconnect, device number 6
[ 1092.092772] BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
[ 1092.101694] PGD 0 P4D 0
[ 1092.104601] Oops: 0000 [#1] SMP
[ 1092.207734] Workqueue: usb_hub_wq hub_event
[ 1092.212507] RIP: 0010:trace_event_raw_event_xhci_log_virt_dev+0x6c/0xf0
[ 1092.220050] RSP: 0018:ffff8c252e883d28 EFLAGS: 00010086
[ 1092.226024] RAX: ffff8c24af86fa84 RBX: 0000000000000003 RCX: ffff8c25255c2a01
[ 1092.234130] RDX: 0000000000000000 RSI: 00000000aef55009 RDI: ffff8c252e883d28
[ 1092.242242] RBP: ffff8c252550e2c0 R08: ffff8c24af86fa84 R09: 0000000000000a70
[ 1092.250364] R10: 0000000000000a70 R11: 0000000000000000 R12: ffff8c251f21a000
[ 1092.258468] R13: 000000000000000c R14: ffff8c251f21a000 R15: ffff8c251f432f60
[ 1092.266572] FS: 0000000000000000(0000) GS:ffff8c252e880000(0000) knlGS:0000000000000000
[ 1092.275757] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1092.282281] CR2: 0000000000000000 CR3: 0000000154209001 CR4: 00000000003606e0
[ 1092.290384] Call Trace:
[ 1092.293156] <IRQ>
[ 1092.295439] xhci_free_virt_device.part.34+0x182/0x1a0
[ 1092.301288] handle_cmd_completion+0x7ac/0xfa0
[ 1092.306336] ? trace_event_raw_event_xhci_log_trb+0x6e/0xa0
[ 1092.312661] xhci_irq+0x3e8/0x1f60
[ 1092.316524] __handle_irq_event_percpu+0x75/0x180
[ 1092.321876] handle_irq_event_percpu+0x20/0x50
[ 1092.326922] handle_irq_event+0x36/0x60
[ 1092.331273] handle_edge_irq+0x6d/0x180
[ 1092.335644] handle_irq+0x16/0x20
[ 1092.339417] do_IRQ+0x41/0xc0
[ 1092.342782] common_interrupt+0xf/0xf
[ 1092.346955] </IRQ>
Fixes: 44a182b9d177 ("xhci: Fix use-after-free in xhci_free_virt_device")
Cc: <stable@vger.kernel.org>
Signed-off-by: Zhengjun Xing <zhengjun.xing@linux.intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rw-r--r-- | drivers/usb/host/xhci-mem.c | 4 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-trace.h | 36 |
2 files changed, 33 insertions, 7 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index acbd3d7b8828..8a62eee9eee1 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
| @@ -886,12 +886,12 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) | |||
| 886 | 886 | ||
| 887 | dev = xhci->devs[slot_id]; | 887 | dev = xhci->devs[slot_id]; |
| 888 | 888 | ||
| 889 | trace_xhci_free_virt_device(dev); | ||
| 890 | |||
| 891 | xhci->dcbaa->dev_context_ptrs[slot_id] = 0; | 889 | xhci->dcbaa->dev_context_ptrs[slot_id] = 0; |
| 892 | if (!dev) | 890 | if (!dev) |
| 893 | return; | 891 | return; |
| 894 | 892 | ||
| 893 | trace_xhci_free_virt_device(dev); | ||
| 894 | |||
| 895 | if (dev->tt_info) | 895 | if (dev->tt_info) |
| 896 | old_active_eps = dev->tt_info->active_eps; | 896 | old_active_eps = dev->tt_info->active_eps; |
| 897 | 897 | ||
diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h index 410544ffe78f..88b427434bd8 100644 --- a/drivers/usb/host/xhci-trace.h +++ b/drivers/usb/host/xhci-trace.h | |||
| @@ -171,6 +171,37 @@ DEFINE_EVENT(xhci_log_trb, xhci_dbc_gadget_ep_queue, | |||
| 171 | TP_ARGS(ring, trb) | 171 | TP_ARGS(ring, trb) |
| 172 | ); | 172 | ); |
| 173 | 173 | ||
| 174 | DECLARE_EVENT_CLASS(xhci_log_free_virt_dev, | ||
| 175 | TP_PROTO(struct xhci_virt_device *vdev), | ||
| 176 | TP_ARGS(vdev), | ||
| 177 | TP_STRUCT__entry( | ||
| 178 | __field(void *, vdev) | ||
| 179 | __field(unsigned long long, out_ctx) | ||
| 180 | __field(unsigned long long, in_ctx) | ||
| 181 | __field(u8, fake_port) | ||
| 182 | __field(u8, real_port) | ||
| 183 | __field(u16, current_mel) | ||
| 184 | |||
| 185 | ), | ||
| 186 | TP_fast_assign( | ||
| 187 | __entry->vdev = vdev; | ||
| 188 | __entry->in_ctx = (unsigned long long) vdev->in_ctx->dma; | ||
| 189 | __entry->out_ctx = (unsigned long long) vdev->out_ctx->dma; | ||
| 190 | __entry->fake_port = (u8) vdev->fake_port; | ||
| 191 | __entry->real_port = (u8) vdev->real_port; | ||
| 192 | __entry->current_mel = (u16) vdev->current_mel; | ||
| 193 | ), | ||
| 194 | TP_printk("vdev %p ctx %llx | %llx fake_port %d real_port %d current_mel %d", | ||
| 195 | __entry->vdev, __entry->in_ctx, __entry->out_ctx, | ||
| 196 | __entry->fake_port, __entry->real_port, __entry->current_mel | ||
| 197 | ) | ||
| 198 | ); | ||
| 199 | |||
| 200 | DEFINE_EVENT(xhci_log_free_virt_dev, xhci_free_virt_device, | ||
| 201 | TP_PROTO(struct xhci_virt_device *vdev), | ||
| 202 | TP_ARGS(vdev) | ||
| 203 | ); | ||
| 204 | |||
| 174 | DECLARE_EVENT_CLASS(xhci_log_virt_dev, | 205 | DECLARE_EVENT_CLASS(xhci_log_virt_dev, |
| 175 | TP_PROTO(struct xhci_virt_device *vdev), | 206 | TP_PROTO(struct xhci_virt_device *vdev), |
| 176 | TP_ARGS(vdev), | 207 | TP_ARGS(vdev), |
| @@ -208,11 +239,6 @@ DEFINE_EVENT(xhci_log_virt_dev, xhci_alloc_virt_device, | |||
| 208 | TP_ARGS(vdev) | 239 | TP_ARGS(vdev) |
| 209 | ); | 240 | ); |
| 210 | 241 | ||
| 211 | DEFINE_EVENT(xhci_log_virt_dev, xhci_free_virt_device, | ||
| 212 | TP_PROTO(struct xhci_virt_device *vdev), | ||
| 213 | TP_ARGS(vdev) | ||
| 214 | ); | ||
| 215 | |||
| 216 | DEFINE_EVENT(xhci_log_virt_dev, xhci_setup_device, | 242 | DEFINE_EVENT(xhci_log_virt_dev, xhci_setup_device, |
| 217 | TP_PROTO(struct xhci_virt_device *vdev), | 243 | TP_PROTO(struct xhci_virt_device *vdev), |
| 218 | TP_ARGS(vdev) | 244 | TP_ARGS(vdev) |
