| From foo@baz Mon Sep 17 12:33:31 CEST 2018 |
| From: Anton Vasilyev <vasilyev@ispras.ru> |
| Date: Fri, 27 Jul 2018 07:52:20 -0400 |
| Subject: media: davinci: vpif_display: Mix memory leak on probe error path |
| |
| From: Anton Vasilyev <vasilyev@ispras.ru> |
| |
| [ Upstream commit 61e641f36ed81ae473177c085f0bfd83ad3b55ed ] |
| |
| If vpif_probe() fails on v4l2_device_register() then memory allocated |
| at initialize_vpif() for global vpif_obj.dev[i] become unreleased. |
| |
| The patch adds deallocation of vpif_obj.dev[i] on the error path and |
| removes duplicated check on platform_data presence. |
| |
| Found by Linux Driver Verification project (linuxtesting.org). |
| |
| Signed-off-by: Anton Vasilyev <vasilyev@ispras.ru> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/media/platform/davinci/vpif_display.c | 24 ++++++++++++++++-------- |
| 1 file changed, 16 insertions(+), 8 deletions(-) |
| |
| --- a/drivers/media/platform/davinci/vpif_display.c |
| +++ b/drivers/media/platform/davinci/vpif_display.c |
| @@ -1114,6 +1114,14 @@ vpif_init_free_channel_objects: |
| return err; |
| } |
| |
| +static void free_vpif_objs(void) |
| +{ |
| + int i; |
| + |
| + for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) |
| + kfree(vpif_obj.dev[i]); |
| +} |
| + |
| static int vpif_async_bound(struct v4l2_async_notifier *notifier, |
| struct v4l2_subdev *subdev, |
| struct v4l2_async_subdev *asd) |
| @@ -1250,11 +1258,6 @@ static __init int vpif_probe(struct plat |
| return -EINVAL; |
| } |
| |
| - if (!pdev->dev.platform_data) { |
| - dev_warn(&pdev->dev, "Missing platform data. Giving up.\n"); |
| - return -EINVAL; |
| - } |
| - |
| vpif_dev = &pdev->dev; |
| err = initialize_vpif(); |
| |
| @@ -1266,7 +1269,7 @@ static __init int vpif_probe(struct plat |
| err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev); |
| if (err) { |
| v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n"); |
| - return err; |
| + goto vpif_free; |
| } |
| |
| while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { |
| @@ -1309,7 +1312,10 @@ static __init int vpif_probe(struct plat |
| if (vpif_obj.sd[i]) |
| vpif_obj.sd[i]->grp_id = 1 << i; |
| } |
| - vpif_probe_complete(); |
| + err = vpif_probe_complete(); |
| + if (err) { |
| + goto probe_subdev_out; |
| + } |
| } else { |
| vpif_obj.notifier.subdevs = vpif_obj.config->asd; |
| vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; |
| @@ -1330,6 +1336,8 @@ probe_subdev_out: |
| kfree(vpif_obj.sd); |
| vpif_unregister: |
| v4l2_device_unregister(&vpif_obj.v4l2_dev); |
| +vpif_free: |
| + free_vpif_objs(); |
| |
| return err; |
| } |
| @@ -1351,8 +1359,8 @@ static int vpif_remove(struct platform_d |
| ch = vpif_obj.dev[i]; |
| /* Unregister video device */ |
| video_unregister_device(&ch->video_dev); |
| - kfree(vpif_obj.dev[i]); |
| } |
| + free_vpif_objs(); |
| |
| return 0; |
| } |