[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20241105154927.GA6317@pendragon.ideasonboard.com>
Date: Tue, 5 Nov 2024 17:49:27 +0200
From: Laurent Pinchart <laurent.pinchart@...asonboard.com>
To: Ricardo Ribalda <ribalda@...omium.org>
Cc: Mauro Carvalho Chehab <mchehab@...nel.org>, linux-media@...r.kernel.org,
linux-kernel@...r.kernel.org, Hans Verkuil <hverkuil@...all.nl>
Subject: Re: [PATCH] media: uvcvideo: Remove refcounted cleanup
On Tue, Nov 05, 2024 at 04:36:38PM +0100, Ricardo Ribalda wrote:
> On Tue, 5 Nov 2024 at 15:43, Laurent Pinchart wrote:
> > On Tue, Nov 05, 2024 at 02:32:39PM +0000, Ricardo Ribalda wrote:
> > > After commit c9ec6f173636 ("media: uvcvideo: Stop stream during unregister")
> > > we have some guarantee that userspace will not be able to access any of
> > > our internal structures after disconnect().
> > >
> > > This means that we can do the cleanup at the end of disconnect and make
> > > the code more resilient to races.
> > >
> > > This change will also enable the use of devres functions in more parts
> > > of the code.
> >
> > That's the wrong direction, let's not go there, especially given that
> > this doesn't fix anything. Strong nack on my side, especially given how
> > many of your previous patches introduced race conditions. It's not
>
> They have also fixed some race conditions... keep the discussion
> professional please.
>
> I think this only proves that uvc code is quite complicated. It also
> lacks a lot of consistency with the rest of the drivers in media (and
> in the kernel in general)
> that is exactly what this patch tries to fix.
>
> > broken, don't touch it. A better use of your time would be to fix the
> > unplug race issue at the subsystem level.
>
> Now memory is allocated during uvc_probe(), but it is not freed until
> after disconnect() if userspace has a videodevice open.
> Luckily userspace now cannot interfere with the driver after
> disconnect(), so lets make use of that property to simplify the code.
>
> As the commit message says, with this change we can start using devm_
> functions and we will have less chances to make mistakes
> Eg: no more
> - this cleanout belongs to uvc_register_video_device vs uvc_delete
> - devm_ function fails because it is called too late
>
> This patch fixes a class of bugs. I would really appreciate it if you
> can review it.
> I have moved it to its own patchset:
> https://patchwork.linuxtv.org/project/linux-media/patch/20241105-uvc-rmrefcount-v1-1-123f56b01731@chromium.org/
> I am planning to send more patches on top of it making use of devres
I currently lack confidence in your patches when it comes to race
conditions and use-after-free. For the ones that fix bugs, or introduce
new features, I bite the bullet and review them. The most recent example
(https://lore.kernel.org/r/20241105-uvc-crashrmmod-v5-1-8623fa51a74f@chromium.org)
is a good example of why I lack that confidence. I will prioritize my
time to get important uvcvideo patches in as quickly as possible, not on
reviewing patches that do not address any issue and have a high risk of
introducing problems.
If you would like to get this kind of rework in, I recommend rebuilding
bridges first and creating trust. I would request you to drop this patch
in the meantime.
> > > Signed-off-by: Ricardo Ribalda <ribalda@...omium.org>
> > > ---
> > > drivers/media/usb/uvc/uvc_driver.c | 24 +++++-------------------
> > > drivers/media/usb/uvc/uvcvideo.h | 1 -
> > > 2 files changed, 5 insertions(+), 20 deletions(-)
> > >
> > > diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
> > > index a96f6ca0889f..2735fccdf454 100644
> > > --- a/drivers/media/usb/uvc/uvc_driver.c
> > > +++ b/drivers/media/usb/uvc/uvc_driver.c
> > > @@ -1868,16 +1868,12 @@ static int uvc_scan_device(struct uvc_device *dev)
> > > /*
> > > * Delete the UVC device.
> > > *
> > > - * Called by the kernel when the last reference to the uvc_device structure
> > > - * is released.
> > > - *
> > > - * As this function is called after or during disconnect(), all URBs have
> > > + * As this function is called during disconnect(), all URBs have
> > > * already been cancelled by the USB core. There is no need to kill the
> > > * interrupt URB manually.
> > > */
> > > -static void uvc_delete(struct kref *kref)
> > > +static void uvc_delete(struct uvc_device *dev)
> > > {
> > > - struct uvc_device *dev = container_of(kref, struct uvc_device, ref);
> > > struct list_head *p, *n;
> > >
> > > uvc_status_cleanup(dev);
> > > @@ -1919,14 +1915,6 @@ static void uvc_delete(struct kref *kref)
> > > kfree(dev);
> > > }
> > >
> > > -static void uvc_release(struct video_device *vdev)
> > > -{
> > > - struct uvc_streaming *stream = video_get_drvdata(vdev);
> > > - struct uvc_device *dev = stream->dev;
> > > -
> > > - kref_put(&dev->ref, uvc_delete);
> > > -}
> > > -
> > > /*
> > > * Unregister the video devices.
> > > */
> > > @@ -2009,7 +1997,7 @@ int uvc_register_video_device(struct uvc_device *dev,
> > > vdev->v4l2_dev = &dev->vdev;
> > > vdev->fops = fops;
> > > vdev->ioctl_ops = ioctl_ops;
> > > - vdev->release = uvc_release;
> > > + vdev->release = video_device_release_empty;
> > > vdev->prio = &stream->chain->prio;
> > > if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
> > > vdev->vfl_dir = VFL_DIR_TX;
> > > @@ -2045,7 +2033,6 @@ int uvc_register_video_device(struct uvc_device *dev,
> > > return ret;
> > > }
> > >
> > > - kref_get(&dev->ref);
> > > return 0;
> > > }
> > >
> > > @@ -2160,7 +2147,6 @@ static int uvc_probe(struct usb_interface *intf,
> > > INIT_LIST_HEAD(&dev->entities);
> > > INIT_LIST_HEAD(&dev->chains);
> > > INIT_LIST_HEAD(&dev->streams);
> > > - kref_init(&dev->ref);
> > > atomic_set(&dev->nmappings, 0);
> > >
> > > dev->udev = usb_get_dev(udev);
> > > @@ -2300,7 +2286,7 @@ static int uvc_probe(struct usb_interface *intf,
> > >
> > > error:
> > > uvc_unregister_video(dev);
> > > - kref_put(&dev->ref, uvc_delete);
> > > + uvc_delete(dev);
> > > return -ENODEV;
> > > }
> > >
> > > @@ -2319,7 +2305,7 @@ static void uvc_disconnect(struct usb_interface *intf)
> > > return;
> > >
> > > uvc_unregister_video(dev);
> > > - kref_put(&dev->ref, uvc_delete);
> > > + uvc_delete(dev);
> > > }
> > >
> > > static int uvc_suspend(struct usb_interface *intf, pm_message_t message)
> > > diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
> > > index 07f9921d83f2..feb8de640a26 100644
> > > --- a/drivers/media/usb/uvc/uvcvideo.h
> > > +++ b/drivers/media/usb/uvc/uvcvideo.h
> > > @@ -578,7 +578,6 @@ struct uvc_device {
> > >
> > > /* Video Streaming interfaces */
> > > struct list_head streams;
> > > - struct kref ref;
> > >
> > > /* Status Interrupt Endpoint */
> > > struct usb_host_endpoint *int_ep;
> > >
> > > ---
> > > base-commit: c7ccf3683ac9746b263b0502255f5ce47f64fe0a
> > > change-id: 20241105-uvc-rmrefcount-010d98d496c5
--
Regards,
Laurent Pinchart
Powered by blists - more mailing lists