Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2d10b29

Browse files
AlanSterngregkh
authored andcommitted
USB: gadget: dummy-hcd: Fix locking bug in RT-enabled kernels
commit 8d63c83 upstream. Yunseong Kim and the syzbot fuzzer both reported a problem in RT-enabled kernels caused by the way dummy-hcd mixes interrupt management and spin-locking. The pattern was: local_irq_save(flags); spin_lock(&dum->lock); ... spin_unlock(&dum->lock); ... // calls usb_gadget_giveback_request() local_irq_restore(flags); The code was written this way because usb_gadget_giveback_request() needs to be called with interrupts disabled and the private lock not held. While this pattern works fine in non-RT kernels, it's not good when RT is enabled. RT kernels handle spinlocks much like mutexes; in particular, spin_lock() may sleep. But sleeping is not allowed while local interrupts are disabled. To fix the problem, rewrite the code to conform to the pattern used elsewhere in dummy-hcd and other UDC drivers: spin_lock_irqsave(&dum->lock, flags); ... spin_unlock(&dum->lock); usb_gadget_giveback_request(...); spin_lock(&dum->lock); ... spin_unlock_irqrestore(&dum->lock, flags); This approach satisfies the RT requirements. Signed-off-by: Alan Stern <[email protected]> Cc: stable <[email protected]> Fixes: b4dbda1 ("USB: dummy-hcd: disable interrupts during req->complete") Reported-by: Yunseong Kim <[email protected]> Closes: <https://lore.kernel.org/linux-usb/[email protected]/> Reported-by: [email protected] Closes: <https://lore.kernel.org/linux-usb/[email protected]/> Tested-by: [email protected] CC: Sebastian Andrzej Siewior <[email protected]> CC: [email protected] Reviewed-by: Sebastian Andrzej Siewior <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent e64b2ff commit 2d10b29

File tree

1 file changed

+4
-4
lines changed

1 file changed

+4
-4
lines changed

drivers/usb/gadget/udc/dummy_hcd.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -764,8 +764,7 @@ static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req)
764764
if (!dum->driver)
765765
return -ESHUTDOWN;
766766

767-
local_irq_save(flags);
768-
spin_lock(&dum->lock);
767+
spin_lock_irqsave(&dum->lock, flags);
769768
list_for_each_entry(iter, &ep->queue, queue) {
770769
if (&iter->req != _req)
771770
continue;
@@ -775,15 +774,16 @@ static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req)
775774
retval = 0;
776775
break;
777776
}
778-
spin_unlock(&dum->lock);
779777

780778
if (retval == 0) {
781779
dev_dbg(udc_dev(dum),
782780
"dequeued req %p from %s, len %d buf %p\n",
783781
req, _ep->name, _req->length, _req->buf);
782+
spin_unlock(&dum->lock);
784783
usb_gadget_giveback_request(_ep, _req);
784+
spin_lock(&dum->lock);
785785
}
786-
local_irq_restore(flags);
786+
spin_unlock_irqrestore(&dum->lock, flags);
787787
return retval;
788788
}
789789

0 commit comments

Comments
 (0)