Skip to content

Commit ea748eb

Browse files
AlanSterngregkh
authored andcommitted
USB: gadget: dummy-hcd: Fix locking bug in RT-enabled kernels
[ Upstream commit 8d63c83 ] 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 <stern@rowland.harvard.edu> Cc: stable <stable@kernel.org> Fixes: b4dbda1 ("USB: dummy-hcd: disable interrupts during req->complete") Reported-by: Yunseong Kim <ysk@kzalloc.com> Closes: <https://lore.kernel.org/linux-usb/5b337389-73b9-4ee4-a83e-7e82bf5af87a@kzalloc.com/> Reported-by: syzbot+8baacc4139f12fa77909@syzkaller.appspotmail.com Closes: <https://lore.kernel.org/linux-usb/68ac2411.050a0220.37038e.0087.GAE@google.com/> Tested-by: syzbot+8baacc4139f12fa77909@syzkaller.appspotmail.com CC: Sebastian Andrzej Siewior <bigeasy@linutronix.de> CC: stable@vger.kernel.org Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Link: https://lore.kernel.org/r/bb192ae2-4eee-48ee-981f-3efdbbd0d8f0@rowland.harvard.edu Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 6070c74 commit ea748eb

1 file changed

Lines changed: 4 additions & 4 deletions

File tree

drivers/usb/gadget/udc/dummy_hcd.c

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

761-
local_irq_save(flags);
762-
spin_lock(&dum->lock);
761+
spin_lock_irqsave(&dum->lock, flags);
763762
list_for_each_entry(iter, &ep->queue, queue) {
764763
if (&iter->req != _req)
765764
continue;
@@ -769,15 +768,16 @@ static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req)
769768
retval = 0;
770769
break;
771770
}
772-
spin_unlock(&dum->lock);
773771

774772
if (retval == 0) {
775773
dev_dbg(udc_dev(dum),
776774
"dequeued req %p from %s, len %d buf %p\n",
777775
req, _ep->name, _req->length, _req->buf);
776+
spin_unlock(&dum->lock);
778777
usb_gadget_giveback_request(_ep, _req);
778+
spin_lock(&dum->lock);
779779
}
780-
local_irq_restore(flags);
780+
spin_unlock_irqrestore(&dum->lock, flags);
781781
return retval;
782782
}
783783

0 commit comments

Comments
 (0)