On Tue Sep 15 19:08:58 2026 +0800, Guangshuo Li wrote:
> tw686x_video_init() registers the V4L2 device, which initializes its
> reference count. Successfully registered video devices take additional
> references to the V4L2 device as well.
> 
> The probe failure paths currently tear down the PCI resources and then
> free the channel arrays and the tw686x device directly. This bypasses
> the V4L2 device reference count and the tw686x_dev_release() callback.
> 
> If a video device still holds a reference, its eventual release will
> drop a reference to the already freed V4L2 device. Even when no extra
> references remain, directly freeing the device bypasses the lifetime
> management established by v4l2_device_register().
> 
> After cleaning up the PCI resources, check whether the V4L2 device was
> registered. If so, mark the hardware unavailable and drop the driver's
> V4L2 device reference, letting tw686x_dev_release() free the backing
> objects when the final reference is released. Keep the existing direct
> free path for failures that occur before V4L2 device registration.
> 
> This issue was found by manual code inspection.
> 
> Fixes: 704a84ccdbf1 ("[media] media: Support Intersil/Techwell TW686x-based 
> video capture cards")
> Cc: [email protected]
> Signed-off-by: Guangshuo Li <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Hans Verkuil

 drivers/media/pci/tw686x/tw686x-core.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

---

diff --git a/drivers/media/pci/tw686x/tw686x-core.c 
b/drivers/media/pci/tw686x/tw686x-core.c
index 5a4ab329c06e..1e3079bb8bb4 100644
--- a/drivers/media/pci/tw686x/tw686x-core.c
+++ b/drivers/media/pci/tw686x/tw686x-core.c
@@ -241,6 +241,7 @@ static int tw686x_probe(struct pci_dev *pci_dev,
                        const struct pci_device_id *pci_id)
 {
        struct tw686x_dev *dev;
+       unsigned long flags;
        int err;
 
        dev = kzalloc_obj(*dev);
@@ -352,6 +353,15 @@ free_region:
        pci_release_regions(pci_dev);
 disable_pci:
        pci_disable_device(pci_dev);
+       if (dev->v4l2_dev.dev) {
+               spin_lock_irqsave(&dev->lock, flags);
+               dev->pci_dev = NULL;
+               spin_unlock_irqrestore(&dev->lock, flags);
+
+               v4l2_device_put(&dev->v4l2_dev);
+               return err;
+       }
+
 free_audio:
        kfree(dev->audio_channels);
 free_video:
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to