[PATCH] media: usb: siano: initialize URB work once

From: Rohith Matam

Date: Mon Jun 01 2026 - 02:19:47 EST


smsusb_onresponse() reinitializes the URB work item immediately before
scheduling it. If teardown races with a queued work item,
cancel_work_sync() can observe workqueue state with WORK_STRUCT_PWQ
still set and trip the workqueue warning reported by syzbot.

Initialize each work item once when the URB is allocated, then schedule
and cancel that initialized work item for the lifetime of the URB. With
the work item always initialized, smsusb_stop_streaming() can cancel it
unconditionally.

Fixes: ebad8e731c1c ("media: usb: siano: Fix use after free bugs caused by do_submit_urb")
Reported-by: syzbot+0d6ef2b7ceb6014d756c@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=0d6ef2b7ceb6014d756c
Signed-off-by: Rohith Matam <rohithmatham@xxxxxxxxx>
---
drivers/media/usb/siano/smsusb.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c
index 0fdc2e095..4e80ccc20 100644
--- a/drivers/media/usb/siano/smsusb.c
+++ b/drivers/media/usb/siano/smsusb.c
@@ -143,7 +143,6 @@ static void smsusb_onresponse(struct urb *urb)


exit_and_resubmit:
- INIT_WORK(&surb->wq, do_submit_urb);
schedule_work(&surb->wq);
}

@@ -179,8 +178,7 @@ static void smsusb_stop_streaming(struct smsusb_device_t *dev)

for (i = 0; i < MAX_URBS; i++) {
usb_kill_urb(dev->surbs[i].urb);
- if (dev->surbs[i].wq.func)
- cancel_work_sync(&dev->surbs[i].wq);
+ cancel_work_sync(&dev->surbs[i].wq);

if (dev->surbs[i].cb) {
smscore_putbuffer(dev->coredev, dev->surbs[i].cb);
@@ -471,6 +469,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
dev->surbs[i].urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->surbs[i].urb)
goto err_unregister_device;
+ INIT_WORK(&dev->surbs[i].wq, do_submit_urb);
}

pr_debug("smsusb_start_streaming(...).\n");
--
2.47.0