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