]> git.ipfire.org Git - thirdparty/kernel/stable.git/commit
media: uvcvideo: Fix race condition with usb_kill_urb
authorRicardo Ribalda <ribalda@chromium.org>
Thu, 5 Jan 2023 14:31:29 +0000 (15:31 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 11 Mar 2023 12:50:49 +0000 (13:50 +0100)
commitab1d856fbbffda71bf799378b470478b7144e780
treebcda7fdb5ee31b08daebdf3ae62d8e258339e8dc
parent8ed572d5a0f1509e691a75a0e3d3588050371f1e
media: uvcvideo: Fix race condition with usb_kill_urb

commit 619d9b710cf06f7a00a17120ca92333684ac45a8 upstream.

usb_kill_urb warranties that all the handlers are finished when it
returns, but does not protect against threads that might be handling
asynchronously the urb.

For UVC, the function uvc_ctrl_status_event_async() takes care of
control changes asynchronously.

If the code is executed in the following order:

CPU 0 CPU 1
=====  =====
uvc_status_complete()
uvc_status_stop()
uvc_ctrl_status_event_work()
uvc_status_start() -> FAIL

Then uvc_status_start will keep failing and this error will be shown:

<4>[    5.540139] URB 0000000000000000 submitted while active
drivers/usb/core/urb.c:378 usb_submit_urb+0x4c3/0x528

Let's improve the current situation, by not re-submiting the urb if
we are stopping the status event. Also process the queued work
(if any) during stop.

CPU 0 CPU 1
=====  =====
uvc_status_complete()
uvc_status_stop()
uvc_status_start()
uvc_ctrl_status_event_work() -> FAIL

Hopefully, with the usb layer protection this should be enough to cover
all the cases.

Cc: stable@vger.kernel.org
Fixes: e5225c820c05 ("media: uvcvideo: Send a control event when a Control Change interrupt arrives")
Reviewed-by: Yunke Cao <yunkec@chromium.org>
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/media/usb/uvc/uvc_ctrl.c
drivers/media/usb/uvc/uvc_status.c
drivers/media/usb/uvc/uvcvideo.h