[PATCH] media: rcar_drif: avoid double free on video register failure

Guangshuo Li posted 1 patch 6 days, 17 hours ago
drivers/media/platform/renesas/rcar_drif.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
[PATCH] media: rcar_drif: avoid double free on video register failure
Posted by Guangshuo Li 6 days, 17 hours ago
rcar_drif_sdr_register() allocates a video_device with
video_device_alloc() and releases it if video_register_device() fails.

This can double free the video_device when __video_register_device()
reaches device_register() and that call fails:

  video_register_device()
    -> __video_register_device()
       -> device_register() fails
          -> put_device(&vdev->dev)
             -> v4l2_device_release()
                -> vdev->release(vdev)
                   -> video_device_release(vdev)

  rcar_drif_sdr_register()
    -> video_device_release(sdr->vdev)

Use video_device_release_empty() while registering the device so that
registration failure paths do not free sdr->vdev through vdev->release().
rcar_drif_sdr_register() then releases sdr->vdev exactly once on failure.
Restore video_device_release() after successful registration so the
registered device keeps its normal lifetime handling.

This issue was found by a static analysis tool I am developing.

Fixes: 7625ee981af1 ("[media] media: platform: rcar_drif: Add DRIF support")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
 drivers/media/platform/renesas/rcar_drif.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/renesas/rcar_drif.c b/drivers/media/platform/renesas/rcar_drif.c
index 0844934f7aa6..19c5c2823176 100644
--- a/drivers/media/platform/renesas/rcar_drif.c
+++ b/drivers/media/platform/renesas/rcar_drif.c
@@ -1066,7 +1066,7 @@ static int rcar_drif_sdr_register(struct rcar_drif_sdr *sdr)
 	snprintf(sdr->vdev->name, sizeof(sdr->vdev->name), "R-Car DRIF");
 	sdr->vdev->fops = &rcar_drif_fops;
 	sdr->vdev->ioctl_ops = &rcar_drif_ioctl_ops;
-	sdr->vdev->release = video_device_release;
+	sdr->vdev->release = video_device_release_empty;
 	sdr->vdev->lock = &sdr->v4l2_mutex;
 	sdr->vdev->queue = &sdr->vb_queue;
 	sdr->vdev->ctrl_handler = &sdr->ctrl_hdl;
@@ -1082,6 +1082,7 @@ static int rcar_drif_sdr_register(struct rcar_drif_sdr *sdr)
 		sdr->vdev = NULL;
 		dev_err(sdr->dev, "failed video_register_device (%d)\n", ret);
 	}
+	sdr->vdev->release = video_device_release;
 
 	return ret;
 }
-- 
2.43.0