From: Greg Kroah-Hartman Date: Fri, 10 Mar 2023 12:14:50 +0000 (+0100) Subject: drop queue-4.19/media-uvcvideo-fix-race-condition-with-usb_kill_urb.patch X-Git-Tag: v6.1.17~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c78b8f56359f93cd95c9d1b3d38d66568a8fc5f7;p=thirdparty%2Fkernel%2Fstable-queue.git drop queue-4.19/media-uvcvideo-fix-race-condition-with-usb_kill_urb.patch --- diff --git a/queue-4.19/media-uvcvideo-fix-race-condition-with-usb_kill_urb.patch b/queue-4.19/media-uvcvideo-fix-race-condition-with-usb_kill_urb.patch deleted file mode 100644 index c33d5127d5f..00000000000 --- a/queue-4.19/media-uvcvideo-fix-race-condition-with-usb_kill_urb.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 619d9b710cf06f7a00a17120ca92333684ac45a8 Mon Sep 17 00:00:00 2001 -From: Ricardo Ribalda -Date: Thu, 5 Jan 2023 15:31:29 +0100 -Subject: media: uvcvideo: Fix race condition with usb_kill_urb - -From: Ricardo Ribalda - -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 -Signed-off-by: Ricardo Ribalda -Reviewed-by: Laurent Pinchart -Signed-off-by: Laurent Pinchart -Signed-off-by: Greg Kroah-Hartman ---- - drivers/media/usb/uvc/uvc_ctrl.c | 5 +++++ - drivers/media/usb/uvc/uvc_status.c | 37 +++++++++++++++++++++++++++++++++++++ - drivers/media/usb/uvc/uvcvideo.h | 1 + - 3 files changed, 43 insertions(+) - ---- a/drivers/media/usb/uvc/uvc_ctrl.c -+++ b/drivers/media/usb/uvc/uvc_ctrl.c -@@ -11,6 +11,7 @@ - * - */ - -+#include - #include - #include - #include -@@ -1318,6 +1319,10 @@ static void uvc_ctrl_status_event_work(s - - mutex_unlock(&chain->ctrl_mutex); - -+ /* The barrier is needed to synchronize with uvc_status_stop(). */ -+ if (smp_load_acquire(&dev->flush_status)) -+ return; -+ - /* Resubmit the URB. */ - w->urb->interval = dev->int_ep->desc.bInterval; - ret = usb_submit_urb(w->urb, GFP_KERNEL); ---- a/drivers/media/usb/uvc/uvc_status.c -+++ b/drivers/media/usb/uvc/uvc_status.c -@@ -11,6 +11,7 @@ - * - */ - -+#include - #include - #include - #include -@@ -314,5 +315,41 @@ int uvc_status_start(struct uvc_device * - - void uvc_status_stop(struct uvc_device *dev) - { -+ struct uvc_ctrl_work *w = &dev->async_ctrl; -+ -+ /* -+ * Prevent the asynchronous control handler from requeing the URB. The -+ * barrier is needed so the flush_status change is visible to other -+ * CPUs running the asynchronous handler before usb_kill_urb() is -+ * called below. -+ */ -+ smp_store_release(&dev->flush_status, true); -+ -+ /* -+ * Cancel any pending asynchronous work. If any status event was queued, -+ * process it synchronously. -+ */ -+ if (cancel_work_sync(&w->work)) -+ uvc_ctrl_status_event(w->chain, w->ctrl, w->data); -+ -+ /* Kill the urb. */ - usb_kill_urb(dev->int_urb); -+ -+ /* -+ * The URB completion handler may have queued asynchronous work. This -+ * won't resubmit the URB as flush_status is set, but it needs to be -+ * cancelled before returning or it could then race with a future -+ * uvc_status_start() call. -+ */ -+ if (cancel_work_sync(&w->work)) -+ uvc_ctrl_status_event(w->chain, w->ctrl, w->data); -+ -+ /* -+ * From this point, there are no events on the queue and the status URB -+ * is dead. No events will be queued until uvc_status_start() is called. -+ * The barrier is needed to make sure that flush_status is visible to -+ * uvc_ctrl_status_event_work() when uvc_status_start() will be called -+ * again. -+ */ -+ smp_store_release(&dev->flush_status, false); - } ---- a/drivers/media/usb/uvc/uvcvideo.h -+++ b/drivers/media/usb/uvc/uvcvideo.h -@@ -603,6 +603,7 @@ struct uvc_device { - /* Status Interrupt Endpoint */ - struct usb_host_endpoint *int_ep; - struct urb *int_urb; -+ bool flush_status; - u8 *status; - struct input_dev *input; - char input_phys[64]; diff --git a/queue-4.19/series b/queue-4.19/series index f0a3f72e609..6a1ad2b6bb4 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -245,5 +245,4 @@ phy-rockchip-typec-fix-unsigned-comparison-with-less.patch bluetooth-hci_sock-purge-socket-queues-in-the-destruct-callback.patch s390-maccess-add-no-dat-mode-to-kernel_write.patch s390-setup-init-jump-labels-before-command-line-parsing.patch -media-uvcvideo-fix-race-condition-with-usb_kill_urb.patch tcp-fix-listen-regression-in-5.15.88.patch