On Fri Jul 17 15:42:45 2026 +0200, Hans Verkuil wrote:
> This reverts commit 2a934fdb01db6458288fc9386d3d8ceba6dd551a.
> 
> The intentions of that patch were good, but it doesn't work.
> 
> The idea is that if device_register fails, you have to do a put_device
> to let the ref counter release resources.
> 
> However, the V4L2 API says that if video_register_device() fails, then
> you have to call video_device_release(), which kfree()s the video_device
> struct.
> 
> But the put_device() will already have freed the struct, so you end
> up in a double-free scenario.
> 
> There is not really a good way of fixing this without breaking
> video_register_device() into two parts, one that initializes everything,
> and one that does the actual device_register, and then converting all
> V4L2 drivers to this new model.
> 
> That is a massive job, and it is very unlikely that device_register
> will fail.
> 
> So rather than ending up in a double-free scenario, just revert this
> patch, and in that case we'll have a small memory leak. Which is a lot
> more robust.
> 
> Reviewed-by: Laurent Pinchart <[email protected]>
> Fixes: 2a934fdb01db ("media: v4l2-dev: fix error handling in 
> __video_register_device()")
> Cc: [email protected]
> Link: 
> https://lore.kernel.org/linux-media/[email protected]/
> Link: https://lore.kernel.org/all/2026042058-charm-storable-4ad8@gregkh/
> Signed-off-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Hans Verkuil

 drivers/media/v4l2-core/v4l2-dev.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

---

diff --git a/drivers/media/v4l2-core/v4l2-dev.c 
b/drivers/media/v4l2-core/v4l2-dev.c
index 5516b2bbb08f..d750bf10febe 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -1071,25 +1071,25 @@ int __video_register_device(struct video_device *vdev,
        vdev->dev.class = &video_class;
        vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);
        vdev->dev.parent = vdev->dev_parent;
-       vdev->dev.release = v4l2_device_release;
        dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);
-
-       /* Increase v4l2_device refcount */
-       v4l2_device_get(vdev->v4l2_dev);
-
        mutex_lock(&videodev_lock);
        ret = device_register(&vdev->dev);
        if (ret < 0) {
                mutex_unlock(&videodev_lock);
                pr_err("%s: device_register failed\n", __func__);
-               put_device(&vdev->dev);
-               return ret;
+               goto cleanup;
        }
+       /* Register the release callback that will be called when the last
+          reference to the device goes away. */
+       vdev->dev.release = v4l2_device_release;
 
        if (nr != -1 && nr != vdev->num && warn_if_nr_in_use)
                pr_warn("%s: requested %s%d, got %s\n", __func__,
                        name_base, nr, video_device_node_name(vdev));
 
+       /* Increase v4l2_device refcount */
+       v4l2_device_get(vdev->v4l2_dev);
+
        /* Part 5: Register the entity. */
        ret = video_register_media_controller(vdev);
 
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to