summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2012-10-16 13:17:43 -0700
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2012-10-25 13:13:47 -0700
commit43a09f7fb01fa1e091416a2aa49b6c666458c1ee (patch)
tree93ea7c67e4bff6051cc652878b71fe75fd21825d
parent8daf8b6086f9d575200cd0aa3797e26137255609 (diff)
downloadlinux-3.10-43a09f7fb01fa1e091416a2aa49b6c666458c1ee.tar.gz
linux-3.10-43a09f7fb01fa1e091416a2aa49b6c666458c1ee.tar.bz2
linux-3.10-43a09f7fb01fa1e091416a2aa49b6c666458c1ee.zip
xhci: Fix potential NULL ptr deref in command cancellation.
The command cancellation code doesn't check whether find_trb_seg() couldn't find the segment that contains the TRB to be canceled. This could cause a NULL pointer deference later in the function when next_trb is called. It's unlikely to happen unless something is wrong with the command ring pointers, so add some debugging in case it happens. This patch should be backported to stable kernels as old as 3.0, that contain the commit b63f4053cc8aa22a98e3f9a97845afe6c15d0a0d "xHCI: handle command after aborting the command ring". Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Cc: stable@vger.kernel.org
-rw-r--r--drivers/usb/host/xhci-ring.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index c6ebb176dc4..4e1a8946b8d 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1228,6 +1228,17 @@ static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd)
cur_seg = find_trb_seg(xhci->cmd_ring->first_seg,
xhci->cmd_ring->dequeue, &cycle_state);
+ if (!cur_seg) {
+ xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n",
+ xhci->cmd_ring->dequeue,
+ (unsigned long long)
+ xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
+ xhci->cmd_ring->dequeue));
+ xhci_debug_ring(xhci, xhci->cmd_ring);
+ xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
+ return;
+ }
+
/* find the command trb matched by cd from command ring */
for (cmd_trb = xhci->cmd_ring->dequeue;
cmd_trb != xhci->cmd_ring->enqueue;