summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Nyman <mathias.nyman@linux.intel.com>2017-07-20 14:48:26 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-07-27 15:08:00 -0700
commit01845a8347b73ddc89c0e7a81a108a4786ff07ea (patch)
tree14c82cf43015655d8758c78599a6001145b4ac4a
parentbf0440882ea94629b198b132ce89c11e25b4b91d (diff)
xhci: Fix NULL pointer dereference when cleaning up streams for removed host
commit 4b895868bb2da60a386a17cde3bf9ecbc70c79f4 upstream. This off by one in stream_id indexing caused NULL pointer dereference and soft lockup on machines with USB attached SCSI devices connected to a hotpluggable xhci controller. The code that cleans up pending URBs for dead hosts tried to dereference a stream ring at the invalid stream_id 0. ep->stream_info->stream_rings[0] doesn't point to a ring. Start looping stream_id from 1 like in all the other places in the driver, and check that the ring exists before trying to kill URBs on it. Reported-by: rocko r <rockorequin@gmail.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-ring.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 521c1816a26a..63735b5310bb 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -860,13 +860,16 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci,
(ep->ep_state & EP_GETTING_NO_STREAMS)) {
int stream_id;
- for (stream_id = 0; stream_id < ep->stream_info->num_streams;
+ for (stream_id = 1; stream_id < ep->stream_info->num_streams;
stream_id++) {
+ ring = ep->stream_info->stream_rings[stream_id];
+ if (!ring)
+ continue;
+
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"Killing URBs for slot ID %u, ep index %u, stream %u",
- slot_id, ep_index, stream_id + 1);
- xhci_kill_ring_urbs(xhci,
- ep->stream_info->stream_rings[stream_id]);
+ slot_id, ep_index, stream_id);
+ xhci_kill_ring_urbs(xhci, ring);
}
} else {
ring = ep->ring;