On Fri, Aug 17, 2012 at 01:38:22PM -0400, Gregs git-bot wrote:
> commit: 50d0206fcaea3e736f912fd5b00ec6233fb4ce44
> From: Sarah Sharp <[email protected]>
> Date: Thu, 26 Jul 2012 12:03:59 -0700
> Subject: xhci: Fix bug after deq ptr set to link TRB.
> 
> This patch fixes a particularly nasty bug that was revealed by the ring
> expansion patches.  The bug has been present since the very beginning of
> the xHCI driver history, and could have caused general protection faults
> from bad memory accesses.
> 
> The first thing to note is that a Set TR Dequeue Pointer command can
> move the dequeue pointer to a link TRB, if the canceled or stalled
> transfer TD ended just before a link TRB.  The function to increment the
> dequeue pointer, inc_deq, was written before cancellation and stall
> support was added.  It assumed that the dequeue pointer could never
> point to a link TRB.  It would unconditionally increment the dequeue
> pointer at the start of the function, check if the pointer was now on a
> link TRB, and move it to the top of the next segment if so.
> 
> This means that if a Set TR Dequeue Point command moved the dequeue
> pointer to a link TRB, a subsequent call to inc_deq() would move the
> pointer off the segment and into la-la-land.  It would then read from
> that memory to determine if it was a link TRB.  Other functions would
> often call inc_deq() until the dequeue pointer matched some other
> pointer, which means this function would quite happily read all of
> system memory before wrapping around to the right pointer value.
> 
> Often, there would be another endpoint segment from a different ring
> allocated from the same DMA pool, which would be contiguous to the
> segment inc_deq just stepped off of.  inc_deq would eventually find the
> link TRB in that segment, and blindly move the dequeue pointer back to
> the top of the correct ring segment.
> 
> The only reason the original code worked at all is because there was
> only one ring segment.  With the ring expansion patches, the dequeue
> pointer would eventually wrap into place, but the dequeue segment would
> be out-of-sync.  On the second TD after the dequeue pointer was moved to
> a link TRB, trb_in_td() would fail (because the dequeue pointer and
> dequeue segment were out-of-sync), and this message would appear:
> 
> ERROR Transfer event TRB DMA ptr not part of current TD
> 
> This fixes bugzilla entry 4333 (option-based modem unhappy on USB 3.0
> port: "Transfer event TRB DMA ptr not part of current TD", "rejecting
> I/O to offline device"),
> 
>       https://bugzilla.kernel.org/show_bug.cgi?id=43333
> 
> and possibly other general protection fault bugs as well.
> 
> This patch should be backported to kernels as old as 2.6.31.  A separate
> patch will be created for kernels older than 3.4, since inc_deq was
> modified in 3.4 and this patch will not apply.

Care to provide that patch now?

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to