summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/function/uvc_v4l2.c
diff options
context:
space:
mode:
authorAvichal Rakesh <arakesh@google.com>2023-11-08 16:41:04 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-11-23 12:32:44 +0000
commitda324ffce34c521b239f319d4051260444a3eb4a (patch)
treec10c0db5864fb4a81818b026f144b4f079b9ed87 /drivers/usb/gadget/function/uvc_v4l2.c
parent2079b60bda3257146a4e8ed7525513865f7e6b3e (diff)
usb: gadget: uvc: Fix use-after-free for inflight usb_requests
Currently, the uvc gadget driver allocates all uvc_requests as one array and deallocates them all when the video stream stops. This includes de-allocating all the usb_requests associated with those uvc_requests. This can lead to use-after-free issues if any of those de-allocated usb_requests were still owned by the usb controller. This is patch 2 of 2 in fixing the use-after-free issue. It adds a new flag to uvc_video to track when frames and requests should be flowing. When disabling the video stream, the flag is tripped and, instead of de-allocating all uvc_requests and usb_requests, the gadget driver only de-allocates those usb_requests that are currently owned by it (as present in req_free). Other usb_requests are left untouched until their completion handler is called which takes care of freeing the usb_request and its corresponding uvc_request. Now that uvc_video does not depends on uvc->state, this patch removes unnecessary upates to uvc->state that were made to accommodate uvc_video logic. This should ensure that uvc gadget driver never accidentally de-allocates a usb_request that it doesn't own. Link: https://lore.kernel.org/7cd81649-2795-45b6-8c10-b7df1055020d@google.com Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com> Reviewed-by: Michael Grzeschik <m.grzeschik@pengutronix.de> Suggested-by: Michael Grzeschik <m.grzeschik@pengutronix.de> Tested-by: Michael Grzeschik <m.grzeschik@pengutronix.de> Signed-off-by: Avichal Rakesh <arakesh@google.com> Link: https://lore.kernel.org/r/20231109004104.3467968-4-arakesh@google.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/gadget/function/uvc_v4l2.c')
-rw-r--r--drivers/usb/gadget/function/uvc_v4l2.c10
1 files changed, 1 insertions, 9 deletions
diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c
index 904dd283cbf7..c7e5fa4f29e0 100644
--- a/drivers/usb/gadget/function/uvc_v4l2.c
+++ b/drivers/usb/gadget/function/uvc_v4l2.c
@@ -468,11 +468,11 @@ uvc_v4l2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
if (type != video->queue.queue.type)
return -EINVAL;
- uvc->state = UVC_STATE_CONNECTED;
ret = uvcg_video_disable(video);
if (ret < 0)
return ret;
+ uvc->state = UVC_STATE_CONNECTED;
uvc_function_setup_continue(uvc, 1);
return 0;
}
@@ -507,14 +507,6 @@ uvc_v4l2_subscribe_event(struct v4l2_fh *fh,
static void uvc_v4l2_disable(struct uvc_device *uvc)
{
uvc_function_disconnect(uvc);
- /*
- * Drop uvc->state to CONNECTED if it was streaming before.
- * This ensures that the usb_requests are no longer queued
- * to the controller.
- */
- if (uvc->state == UVC_STATE_STREAMING)
- uvc->state = UVC_STATE_CONNECTED;
-
uvcg_video_disable(&uvc->video);
uvcg_free_buffers(&uvc->video.queue);
uvc->func_connected = false;