aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathias Nyman <mathias.nyman@linux.intel.com>2017-07-20 07:48:26 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-07-20 08:40:35 -0400
commit4b895868bb2da60a386a17cde3bf9ecbc70c79f4 (patch)
treeb2cda155a97ff5e0e0cbc20889775cb03249e3f8
parent3d69f3a8c2ed1c7f322d23145bc0c3d980ebbacb (diff)
xhci: Fix NULL pointer dereference when cleaning up streams for removed host
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> Cc: <stable@vger.kernel.org> 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 c50c902d009e..cc368ad2b51e 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -864,13 +864,16 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci,
864 (ep->ep_state & EP_GETTING_NO_STREAMS)) { 864 (ep->ep_state & EP_GETTING_NO_STREAMS)) {
865 int stream_id; 865 int stream_id;
866 866
867 for (stream_id = 0; stream_id < ep->stream_info->num_streams; 867 for (stream_id = 1; stream_id < ep->stream_info->num_streams;
868 stream_id++) { 868 stream_id++) {
869 ring = ep->stream_info->stream_rings[stream_id];
870 if (!ring)
871 continue;
872
869 xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, 873 xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
870 "Killing URBs for slot ID %u, ep index %u, stream %u", 874 "Killing URBs for slot ID %u, ep index %u, stream %u",
871 slot_id, ep_index, stream_id + 1); 875 slot_id, ep_index, stream_id);
872 xhci_kill_ring_urbs(xhci, 876 xhci_kill_ring_urbs(xhci, ring);
873 ep->stream_info->stream_rings[stream_id]);
874 } 877 }
875 } else { 878 } else {
876 ring = ep->ring; 879 ring = ep->ring;