summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorAlexey Khoroshilov <khoroshilov@ispras.ru>2016-02-27 01:33:14 +0300
committerFelipe Balbi <balbi@kernel.org>2016-03-04 15:14:47 +0200
commitcff5638ef7852196879f9687e70d49ea291bbb33 (patch)
treec5f7866cbd378848b28157ff007e37972f89db7f /drivers/usb
parentead22caf8507c0533aab6b89e26776414b477b6f (diff)
usb: gadget: bdc_udc: fix race condition in bdc_udc_exit()
bdc_ep_disable() expects to be called with bdc->lock held. The assumption is met in all the cases except for call from bdc_udc_exit(), that is called from bdc_remove(). As a result a race can happen or unheld bdc->lock can be unlocked in bdc_req_complete(). The patch proposes to acquire-release bdc->lock around bdc_ep_disable() in bdc_udc_exit(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru> Signed-off-by: Felipe Balbi <balbi@kernel.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/udc/bdc/bdc_udc.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/usb/gadget/udc/bdc/bdc_udc.c b/drivers/usb/gadget/udc/bdc/bdc_udc.c
index 7f77db5d1278..aae7458d8986 100644
--- a/drivers/usb/gadget/udc/bdc/bdc_udc.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_udc.c
@@ -581,8 +581,13 @@ err0:
void bdc_udc_exit(struct bdc *bdc)
{
+ unsigned long flags;
+
dev_dbg(bdc->dev, "%s()\n", __func__);
+ spin_lock_irqsave(&bdc->lock, flags);
bdc_ep_disable(bdc->bdc_ep_array[1]);
+ spin_unlock_irqrestore(&bdc->lock, flags);
+
usb_del_gadget_udc(&bdc->gadget);
bdc_free_ep(bdc);
}