Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/external/bsd/dwc2 Protect access of urb->hcpriv by adapt...



details:   https://anonhg.NetBSD.org/src/rev/e80b150866c6
branches:  trunk
changeset: 325647:e80b150866c6
user:      skrll <skrll%NetBSD.org@localhost>
date:      Thu Jan 02 15:54:10 2014 +0000

description:
Protect access of urb->hcpriv by adapting the following change from the
Raspberry PI dwc_otg driver.

https://github.com/raspberrypi/linux/commit/38753ce72d4f10d5d0f1ed27fa691a2ba8910941

dwc_otg: prevent OOPSes during device disconnects

The dwc_otg_urb_enqueue function is thread-unsafe. In particular the
access of urb->hcpriv, usb_hcd_link_urb_to_ep, dwc_otg_urb->qtd and
friends does not occur within a critical section and so if a device
was unplugged during activity there was a high chance that the
usbcore hub_thread would try to disable the endpoint with partially-
formed entries in the URB queue. This would result in BUG() or null
pointer dereferences.

Fix so that access of urb->hcpriv, enqueuing to the hardware and
adding to usbcore endpoint URB lists is contained within a single
critical section.

diffstat:

 sys/external/bsd/dwc2/dist/dwc2_hcd.c      |   7 ++-----
 sys/external/bsd/dwc2/dist/dwc2_hcdqueue.c |  13 ++++---------
 sys/external/bsd/dwc2/dwc2.c               |  12 +++++++-----
 3 files changed, 13 insertions(+), 19 deletions(-)

diffs (151 lines):

diff -r 4eb96f7e07f6 -r e80b150866c6 sys/external/bsd/dwc2/dist/dwc2_hcd.c
--- a/sys/external/bsd/dwc2/dist/dwc2_hcd.c     Thu Jan 02 13:07:42 2014 +0000
+++ b/sys/external/bsd/dwc2/dist/dwc2_hcd.c     Thu Jan 02 15:54:10 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: dwc2_hcd.c,v 1.9 2013/11/24 12:25:19 skrll Exp $       */
+/*     $NetBSD: dwc2_hcd.c,v 1.10 2014/01/02 15:54:10 skrll Exp $      */
 
 /*
  * hcd.c - DesignWare HS OTG Controller host-mode routines
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc2_hcd.c,v 1.9 2013/11/24 12:25:19 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc2_hcd.c,v 1.10 2014/01/02 15:54:10 skrll Exp $");
 
 #include <sys/types.h>
 #include <sys/kmem.h>
@@ -367,7 +367,6 @@
 {
        struct dwc2_softc *sc = hsotg->hsotg_sc;
        struct dwc2_qtd *qtd;
-       unsigned long flags;
        u32 intr_mask;
        int retval;
        int dev_speed;
@@ -421,11 +420,9 @@
                         */
                        return 0;
 
-               spin_lock_irqsave(&hsotg->lock, flags);
                tr_type = dwc2_hcd_select_transactions(hsotg);
                if (tr_type != DWC2_TRANSACTION_NONE)
                        dwc2_hcd_queue_transactions(hsotg, tr_type);
-               spin_unlock_irqrestore(&hsotg->lock, flags);
        }
 
        return retval;
diff -r 4eb96f7e07f6 -r e80b150866c6 sys/external/bsd/dwc2/dist/dwc2_hcdqueue.c
--- a/sys/external/bsd/dwc2/dist/dwc2_hcdqueue.c        Thu Jan 02 13:07:42 2014 +0000
+++ b/sys/external/bsd/dwc2/dist/dwc2_hcdqueue.c        Thu Jan 02 15:54:10 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: dwc2_hcdqueue.c,v 1.6 2013/11/24 12:25:19 skrll Exp $  */
+/*     $NetBSD: dwc2_hcdqueue.c,v 1.7 2014/01/02 15:54:10 skrll Exp $  */
 
 /*
  * hcd_queue.c - DesignWare HS OTG Controller host queuing routines
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc2_hcdqueue.c,v 1.6 2013/11/24 12:25:19 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc2_hcdqueue.c,v 1.7 2014/01/02 15:54:10 skrll Exp $");
 
 #include <sys/types.h>
 #include <sys/kmem.h>
@@ -787,12 +787,13 @@
  * Finds the correct QH to place the QTD into. If it does not find a QH, it
  * will create a new QH. If the QH to which the QTD is added is not currently
  * scheduled, it is placed into the proper schedule based on its EP type.
+ *
+ * HCD lock must be held and interrupts must be disabled on entry
  */
 int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
                     struct dwc2_qh **qh, gfp_t mem_flags)
 {
        struct dwc2_hcd_urb *urb = qtd->urb;
-       unsigned long flags;
        int allocated = 0;
        int retval;
 
@@ -807,15 +808,12 @@
                allocated = 1;
        }
 
-       spin_lock_irqsave(&hsotg->lock, flags);
-
        retval = dwc2_hcd_qh_add(hsotg, *qh);
        if (retval)
                goto fail;
 
        qtd->qh = *qh;
        list_add_tail(&qtd->qtd_list_entry, &(*qh)->qtd_list);
-       spin_unlock_irqrestore(&hsotg->lock, flags);
 
        return 0;
 
@@ -832,10 +830,7 @@
                                         qtd_list_entry)
                        dwc2_hcd_qtd_unlink_and_free(hsotg, qtd2, qh_tmp);
 
-               spin_unlock_irqrestore(&hsotg->lock, flags);
                dwc2_hcd_qh_free(hsotg, qh_tmp);
-       } else {
-               spin_unlock_irqrestore(&hsotg->lock, flags);
        }
 
        return retval;
diff -r 4eb96f7e07f6 -r e80b150866c6 sys/external/bsd/dwc2/dwc2.c
--- a/sys/external/bsd/dwc2/dwc2.c      Thu Jan 02 13:07:42 2014 +0000
+++ b/sys/external/bsd/dwc2/dwc2.c      Thu Jan 02 15:54:10 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: dwc2.c,v 1.22 2013/12/31 09:10:43 skrll Exp $  */
+/*     $NetBSD: dwc2.c,v 1.23 2014/01/02 15:54:10 skrll Exp $  */
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.22 2013/12/31 09:10:43 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.23 2014/01/02 15:54:10 skrll Exp $");
 
 #include "opt_usb.h"
 
@@ -1298,7 +1298,6 @@
        memset(dwc2_urb, 0, sizeof(*dwc2_urb) +
            sizeof(dwc2_urb->iso_descs[0]) * DWC2_MAXISOCPACKETS);
 
-       dwc2_urb->priv = xfer;
        dwc2_hcd_urb_set_pipeinfo(hsotg, dwc2_urb, addr, epnum, xfertype, dir,
                                  mps);
 
@@ -1379,6 +1378,9 @@
        }
 
        /* might need to check cpu_intr_p */
+       mutex_spin_enter(&hsotg->lock);
+
+       dwc2_urb->priv = xfer;
        retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, &dpipe->priv, 0);
        if (retval)
                goto fail;
@@ -1389,14 +1391,14 @@
        }
 
        if (alloc_bandwidth) {
-               mutex_spin_enter(&hsotg->lock);
                dwc2_allocate_bus_bandwidth(hsotg,
                                dwc2_hcd_get_ep_bandwidth(hsotg, dpipe),
                                xfer);
-               mutex_spin_exit(&hsotg->lock);
        }
 
 fail:
+       mutex_spin_exit(&hsotg->lock);
+
 //     mutex_exit(&sc->sc_lock);
 
        switch (retval) {



Home | Main Index | Thread Index | Old Index