usb: dwc_otg hcd driver: fix a race condition
authorlyz <lyz@rock-chips.com>
Thu, 19 Jun 2014 03:42:25 +0000 (11:42 +0800)
committerlyz <lyz@rock-chips.com>
Thu, 19 Jun 2014 03:53:01 +0000 (11:53 +0800)
When pannic occurs,
PC is at dwc_otg_hcd_urb_enqueue+0x118/0x184
LR is at dwc_otg_hcd_urb_enqueue+0xf4/0x184
There may be more than one threads running function
dwc_otg_hcd_urb_enqueue().So we should use a spinlock to protect the
dwc_otg_qh_t struct against a use-after-free bug.

drivers/usb/dwc_otg_310/dwc_otg_hcd.c
drivers/usb/dwc_otg_310/dwc_otg_hcd_queue.c

index 30a8bf1fa32cb9af86d694ae181c2ada69fc6718..e8b0ef56913fe79b5a87912e229d7aaa11e53dd7 100755 (executable)
@@ -513,12 +513,11 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t *hcd,
                DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
                return -DWC_E_NO_MEMORY;
        }
-
+       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
        retval =
            dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle,
                                atomic_alloc);
 
-       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
        if (retval < 0) {
                DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
                          "Error status %d\n", retval);
index 04661ce098522871b09798be2bd8306e7f8b999d..faa7327943e647a4e218d484987e098ba40d663c 100755 (executable)
@@ -703,7 +703,6 @@ int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t *qtd,
                        int atomic_alloc)
 {
        int retval = 0;
-       dwc_irqflags_t flags;
 
        dwc_otg_hcd_urb_t *urb = qtd->urb;
 
@@ -719,13 +718,11 @@ int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t *qtd,
                }
        }
        qtd->qh = *qh;
-       DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
        retval = dwc_otg_hcd_qh_add(hcd, *qh);
        if (retval == 0) {
                DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd,
                                        qtd_list_entry);
        }
-       DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
 
 done: