| From eb9c1d5d70093ac4467fd85e507101a8fb01e234 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 16 Sep 2025 09:41:43 +0800 |
| Subject: usbip: Fix locking bug in RT-enabled kernels |
| |
| From: Lizhi Xu <lizhi.xu@windriver.com> |
| |
| [ 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 | 6 +++--- |
| 1 file changed, 3 insertions(+), 3 deletions(-) |
| |
| diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c |
| index b22e0881bfaf..0bc4805cfa3e 100644 |
| --- a/drivers/usb/usbip/vhci_hcd.c |
| +++ b/drivers/usb/usbip/vhci_hcd.c |
| @@ -830,15 +830,15 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag |
| 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; |
| } |
| |
| -- |
| 2.51.0 |
| |