]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
usbip: Fix locking bug in RT-enabled kernels
authorLizhi Xu <lizhi.xu@windriver.com>
Tue, 16 Sep 2025 01:41:43 +0000 (09:41 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Jan 2026 12:11:46 +0000 (13:11 +0100)
[ Upstream commit 09bf21bf5249880f62fe759b53b14b4b52900c6c ]

Interrupts are disabled before entering usb_hcd_giveback_urb().
A spinlock_t becomes a sleeping lock on PREEMPT_RT, so it cannot be
acquired with disabled interrupts.

Save the interrupt status and restore it after usb_hcd_giveback_urb().

syz reported:
BUG: sleeping function called from invalid context at kernel/locking/spinlock_rt.c:48
Call Trace:
 dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
 rt_spin_lock+0xc7/0x2c0 kernel/locking/spinlock_rt.c:57
 spin_lock include/linux/spinlock_rt.h:44 [inline]
 mon_bus_complete drivers/usb/mon/mon_main.c:134 [inline]
 mon_complete+0x5c/0x200 drivers/usb/mon/mon_main.c:147
 usbmon_urb_complete include/linux/usb/hcd.h:738 [inline]
 __usb_hcd_giveback_urb+0x254/0x5e0 drivers/usb/core/hcd.c:1647
 vhci_urb_enqueue+0xb4f/0xe70 drivers/usb/usbip/vhci_hcd.c:818

Reported-by: syzbot+205ef33a3b636b4181fb@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=205ef33a3b636b4181fb
Signed-off-by: Lizhi Xu <lizhi.xu@windriver.com>
Acked-by: Shuah Khan <skhan@linuxfoundation.org>
Link: https://lore.kernel.org/r/20250916014143.1439759-1-lizhi.xu@windriver.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/usb/usbip/vhci_hcd.c

index 2d2506c598818d735383ecd1c9b3b9e9556a1cf3..e5660f0e97e8d7227eb62d00750ada08fbb7bc2b 100644 (file)
@@ -830,15 +830,15 @@ out:
 no_need_xmit:
        usb_hcd_unlink_urb_from_ep(hcd, urb);
 no_need_unlink:
-       spin_unlock_irqrestore(&vhci->lock, flags);
        if (!ret) {
                /* usb_hcd_giveback_urb() should be called with
                 * irqs disabled
                 */
-               local_irq_disable();
+               spin_unlock(&vhci->lock);
                usb_hcd_giveback_urb(hcd, urb, urb->status);
-               local_irq_enable();
+               spin_lock(&vhci->lock);
        }
+       spin_unlock_irqrestore(&vhci->lock, flags);
        return ret;
 }