Skip to content

Commit 8c3d383

Browse files
liubiinnathanchance
authored andcommitted
usb: gadget: fix spinlock dead lock in gadgetfs
[ Upstream commit d246dcb2331c5783743720e6510892eb1d2801d9 ] [ 40.467381] ============================================= [ 40.473013] [ INFO: possible recursive locking detected ] [ 40.478651] 4.6.0-08691-g7f3db9a #37 Not tainted [ 40.483466] --------------------------------------------- [ 40.489098] usb/733 is trying to acquire lock: [ 40.493734] (&(&dev->lock)->rlock){-.....}, at: [<bf129288>] ep0_complete+0x18/0xdc [gadgetfs] [ 40.502882] [ 40.502882] but task is already holding lock: [ 40.508967] (&(&dev->lock)->rlock){-.....}, at: [<bf12a420>] ep0_read+0x20/0x5e0 [gadgetfs] [ 40.517811] [ 40.517811] other info that might help us debug this: [ 40.524623] Possible unsafe locking scenario: [ 40.524623] [ 40.530798] CPU0 [ 40.533346] ---- [ 40.535894] lock(&(&dev->lock)->rlock); [ 40.540088] lock(&(&dev->lock)->rlock); [ 40.544284] [ 40.544284] *** DEADLOCK *** [ 40.544284] [ 40.550461] May be due to missing lock nesting notation [ 40.550461] [ 40.557544] 2 locks held by usb/733: [ 40.561271] #0: (&f->f_pos_lock){+.+.+.}, at: [<c02a6114>] __fdget_pos+0x40/0x48 [ 40.569219] #1: (&(&dev->lock)->rlock){-.....}, at: [<bf12a420>] ep0_read+0x20/0x5e0 [gadgetfs] [ 40.578523] [ 40.578523] stack backtrace: [ 40.583075] CPU: 0 PID: 733 Comm: usb Not tainted 4.6.0-08691-g7f3db9a #37 [ 40.590246] Hardware name: Generic AM33XX (Flattened Device Tree) [ 40.596625] [<c010ffbc>] (unwind_backtrace) from [<c010c1bc>] (show_stack+0x10/0x14) [ 40.604718] [<c010c1bc>] (show_stack) from [<c04207fc>] (dump_stack+0xb0/0xe4) [ 40.612267] [<c04207fc>] (dump_stack) from [<c01886ec>] (__lock_acquire+0xf68/0x1994) [ 40.620440] [<c01886ec>] (__lock_acquire) from [<c0189528>] (lock_acquire+0xd8/0x238) [ 40.628621] [<c0189528>] (lock_acquire) from [<c06ad6b4>] (_raw_spin_lock_irqsave+0x38/0x4c) [ 40.637440] [<c06ad6b4>] (_raw_spin_lock_irqsave) from [<bf129288>] (ep0_complete+0x18/0xdc [gadgetfs]) [ 40.647339] [<bf129288>] (ep0_complete [gadgetfs]) from [<bf10a728>] (musb_g_giveback+0x118/0x1b0 [musb_hdrc]) [ 40.657842] [<bf10a728>] (musb_g_giveback [musb_hdrc]) from [<bf108768>] (musb_g_ep0_queue+0x16c/0x188 [musb_hdrc]) [ 40.668772] [<bf108768>] (musb_g_ep0_queue [musb_hdrc]) from [<bf12a944>] (ep0_read+0x544/0x5e0 [gadgetfs]) [ 40.678963] [<bf12a944>] (ep0_read [gadgetfs]) from [<c0284470>] (__vfs_read+0x20/0x110) [ 40.687414] [<c0284470>] (__vfs_read) from [<c0285324>] (vfs_read+0x88/0x114) [ 40.694864] [<c0285324>] (vfs_read) from [<c0286150>] (SyS_read+0x44/0x9c) [ 40.702051] [<c0286150>] (SyS_read) from [<c0107820>] (ret_fast_syscall+0x0/0x1c) This is caused by the spinlock bug in ep0_read(). Fix the two other deadlock sources in gadgetfs_setup() too. Cc: <[email protected]> # v3.16+ Signed-off-by: Bin Liu <[email protected]> Signed-off-by: Felipe Balbi <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 0654ff1 commit 8c3d383

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

drivers/usb/gadget/legacy/inode.c

+13-4
Original file line numberDiff line numberDiff line change
@@ -1018,8 +1018,11 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
10181018
struct usb_ep *ep = dev->gadget->ep0;
10191019
struct usb_request *req = dev->req;
10201020

1021-
if ((retval = setup_req (ep, req, 0)) == 0)
1022-
retval = usb_ep_queue (ep, req, GFP_ATOMIC);
1021+
if ((retval = setup_req (ep, req, 0)) == 0) {
1022+
spin_unlock_irq (&dev->lock);
1023+
retval = usb_ep_queue (ep, req, GFP_KERNEL);
1024+
spin_lock_irq (&dev->lock);
1025+
}
10231026
dev->state = STATE_DEV_CONNECTED;
10241027

10251028
/* assume that was SET_CONFIGURATION */
@@ -1550,8 +1553,11 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
15501553
w_length);
15511554
if (value < 0)
15521555
break;
1556+
1557+
spin_unlock (&dev->lock);
15531558
value = usb_ep_queue (gadget->ep0, dev->req,
1554-
GFP_ATOMIC);
1559+
GFP_KERNEL);
1560+
spin_lock (&dev->lock);
15551561
if (value < 0) {
15561562
clean_req (gadget->ep0, dev->req);
15571563
break;
@@ -1574,11 +1580,14 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
15741580
if (value >= 0 && dev->state != STATE_DEV_SETUP) {
15751581
req->length = value;
15761582
req->zero = value < w_length;
1577-
value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
1583+
1584+
spin_unlock (&dev->lock);
1585+
value = usb_ep_queue (gadget->ep0, req, GFP_KERNEL);
15781586
if (value < 0) {
15791587
DBG (dev, "ep_queue --> %d\n", value);
15801588
req->status = 0;
15811589
}
1590+
return value;
15821591
}
15831592

15841593
/* device stalls when value < 0 */

0 commit comments

Comments
 (0)