diff options
author | Mathias Nyman <mathias.nyman@linux.intel.com> | 2017-07-20 07:48:26 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-07-20 08:40:35 -0400 |
commit | 4b895868bb2da60a386a17cde3bf9ecbc70c79f4 (patch) | |
tree | b2cda155a97ff5e0e0cbc20889775cb03249e3f8 | |
parent | 3d69f3a8c2ed1c7f322d23145bc0c3d980ebbacb (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.c | 11 |
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; |