[PATCH] media: pvrusb2: initialize workpoll before error paths in pvr2_hdw_create

zhangdaolong posted 1 patch 2 hours ago
drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
[PATCH] media: pvrusb2: initialize workpoll before error paths in pvr2_hdw_create
Posted by zhangdaolong 2 hours ago
In pvr2_hdw_create(), the error handling path under 'fail:' calls
flush_work(&hdw->workpoll) whenever hdw is non-NULL. However,
INIT_WORK(&hdw->workpoll, pvr2_hdw_worker_poll) was placed near the
end of pvr2_hdw_create(), after multiple 'goto fail;' error paths
(such as v4l2_device_register() failure or kmalloc() failures for
control buffers).

If any of those earlier allocations or registrations fail, jumping to
'fail:' invokes flush_work(&hdw->workpoll) on an uninitialized
work_struct where work->func is still NULL, triggering WARN_ON(!work->func)
in __flush_work().

Move INIT_WORK(&hdw->workpoll, pvr2_hdw_worker_poll) right after timer
and waitqueue initialization, before the first error path after hdw
allocation, ensuring workpoll is always initialized before flush_work()
can be called on it.

Fixes: 29a3006e5209 ("[media] pvrusb2: Remove deprecated create_singlethread_workqueue")
Reported-by: syzbot+b91abe6ef9924496daf8@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=b91abe6ef9924496daf8
Signed-off-by: zhangdaolong <dlzhangak@isoftstone.com>
---
 drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
index 3c270ef00752..1fb93f4c8471 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
@@ -2398,6 +2398,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
 	hdw->master_state = PVR2_STATE_DEAD;
 
 	init_waitqueue_head(&hdw->state_wait_data);
+	INIT_WORK(&hdw->workpoll, pvr2_hdw_worker_poll);
 
 	hdw->tuner_signal_stale = !0;
 	cx2341x_fill_defaults(&hdw->enc_ctl_state);
@@ -2567,8 +2568,6 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
 	} while (0);
 	mutex_unlock(&pvr2_unit_mtx);
 
-	INIT_WORK(&hdw->workpoll, pvr2_hdw_worker_poll);
-
 	if (hdw->unit_number == -1)
 		goto fail;
 
-- 
2.48.1