Hello. On 10/29/2012 08:00 PM, Julius Werner wrote: > xhci_alloc_segments_for_ring() builds a list of xhci_segments and links > the tail to head at the end (forming a ring). When it bails out for OOM > reasons half-way through, it tries to destroy its half-built list with > xhci_free_segments_for_ring(), even though it is not a ring yet. This > causes a null-pointer dereference upon hitting the last element. > Furthermore, one of its callers (xhci_ring_alloc()) mistakenly believes > the output parameters to be valid upon this kind of OOM failure, and > calls xhci_ring_free() on them. Since the (incomplete) list/ring should > already be destroyed in that case, this would lead to a use after free. > This patch fixes those issues by having xhci_alloc_segments_for_ring() > destroy its half-built, non-circular list manually and destroying the > invalid struct xhci_ring in xhci_ring_alloc() with a plain kfree(). > Signed-off-by: Julius Werner <jwerner@xxxxxxxxxxxx> > --- > drivers/usb/host/xhci-mem.c | 8 ++++++-- > 1 files changed, 6 insertions(+), 2 deletions(-) > diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c > index 487bc08..420ba37 100644 > --- a/drivers/usb/host/xhci-mem.c > +++ b/drivers/usb/host/xhci-mem.c > @@ -205,7 +205,11 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, > > next = xhci_segment_alloc(xhci, cycle_state, flags); > if (!next) { > - xhci_free_segments_for_ring(xhci, *first); > + prev = *first; > + do { > + next = prev->next; > + xhci_segment_free(xhci, prev); > + } while ((prev = next)); It's preferred that the assignments are done outside the *if* and *while* statements. In fact, at least for the *if* statements scripts/checkpatch.pl gives a warning (it was silent in this case). > return -ENOMEM; > } > xhci_link_segments(xhci, prev, next, type); > @@ -258,7 +262,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, > return ring; > > fail: > - xhci_ring_free(xhci, ring); > + kfree(ring); > return NULL; > } [headless@wasted linux]$ scripts/checkpatch.pl patches/xhci-fix-null-pointer-dereference-when-destroying-half-built-segment-rings.patch ERROR: DOS line endings #30: FILE: drivers/usb/host/xhci-mem.c:208: +^I^I^Iprev = *first;^M$ ERROR: DOS line endings #31: FILE: drivers/usb/host/xhci-mem.c:209: +^I^I^Ido {^M$ ERROR: DOS line endings #32: FILE: drivers/usb/host/xhci-mem.c:210: +^I^I^I^Inext = prev->next;^M$ ERROR: DOS line endings #33: FILE: drivers/usb/host/xhci-mem.c:211: +^I^I^I^Ixhci_segment_free(xhci, prev);^M$ ERROR: DOS line endings #34: FILE: drivers/usb/host/xhci-mem.c:212: +^I^I^I} while ((prev = next));^M$ ERROR: DOS line endings #43: FILE: drivers/usb/host/xhci-mem.c:265: +^Ikfree(ring);^M$ total: 6 errors, 0 warnings, 20 lines checked patches/xhci-fix-null-pointer-dereference-when-destroying-half-built-segment-rings.patch has style problems, please review. If any of these errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. I have noticed that the patch description has DOS line endings as well. WBR, Sergei -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html