[PATCH] media: pvrusb2: fix URB pending flag leak on invalid endpoint
Nguyen Quang Le Kien <[email protected]> Mon, 3 Aug 2026 18:40:08 +0800
| Newsgroups | org.kernel.vger.linux-media,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
In pvr2_send_request_ex(), when usb_urb_ep_type_check() fails for either the write or read control endpoint, the code returned -EINVAL directly without clearing the corresponding pending flags (ctl_write_pend_flag or ctl_read_pend_flag) or going through the done: cleanup path. This left the pending flags set while the URBs were never actually submitted. On the next call to pvr2_send_request_ex(), the URBs would be filled and submitted while the kernel still considered them active, triggering the WARNING "URB submitted while active" in usb_submit_urb(). Fix this by: - Clearing the pending flag before returning on invalid endpoint - Using goto done instead of direct return to go through proper cleanup - For the read endpoint case, unlinking the write URB if it was already submitted and waiting for its completion before returning Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=20fef510634faf733060 Signed-off-by: Nguyen Quang Le Kien <[email protected]> --- drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index 3c270ef00..3a857e95b 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -3669,7 +3669,9 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw, pvr2_trace( PVR2_TRACE_ERROR_LEGS, "Invalid write control endpoint"); - return -EINVAL; + hdw->ctl_write_pend_flag = 0; + status = -EINVAL; + goto done; } status = usb_submit_urb(hdw->ctl_write_urb,GFP_KERNEL); if (status < 0) { @@ -3699,7 +3701,13 @@ status); pvr2_trace( PVR2_TRACE_ERROR_LEGS, "Invalid read control endpoint"); - return -EINVAL; + hdw->ctl_read_pend_flag = 0; + status = -EINVAL; + if (hdw->ctl_write_pend_flag) { + usb_unlink_urb(hdw->ctl_write_urb); + wait_for_completion(&hdw->ctl_done); + } + goto done; } status = usb_submit_urb(hdw->ctl_read_urb,GFP_KERNEL); if (status < 0) { -- 2.34.1