Re: [PATCH] media: uvcvideo: Remove refcounted cleanup

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxx/
> 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@xxxxxxxxxxxx)
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@xxxxxxxxxxxx>
> > > ---
> > >  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




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux