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: stable@vger.kernel.org Signed-off-by: Guangshuo Li --- 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 @@ static int tw686x_probe(struct pci_dev *pci_dev, 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: -- 2.43.0