media: rockchip/rga: fix error handling in probe
There are a few bugs in this code. 1) No checks for whether
dma_alloc_attrs() or __get_free_pages() failed. 2) If
video_register_device() fails it doesn't clean up the dma attrs or the
free pages. 3) The video_device_release() function frees "vfd" which
leads to a use after free on the next line. The call to
video_unregister_device() is not required so I have just removed that.
Fixes: f7e7b48e6d
("[media] rockchip/rga: v4l2 m2m support")
Reported-by: Dongliang Mu <mudongliangabcd@gmail.com>
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
parent
055d2db28e
commit
e58430e1d4
@ -863,12 +863,12 @@ static int rga_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(rga->m2m_dev)) {
|
||||
v4l2_err(&rga->v4l2_dev, "Failed to init mem2mem device\n");
|
||||
ret = PTR_ERR(rga->m2m_dev);
|
||||
goto unreg_video_dev;
|
||||
goto rel_vdev;
|
||||
}
|
||||
|
||||
ret = pm_runtime_resume_and_get(rga->dev);
|
||||
if (ret < 0)
|
||||
goto unreg_video_dev;
|
||||
goto rel_vdev;
|
||||
|
||||
rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
|
||||
rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
|
||||
@ -882,11 +882,23 @@ static int rga_probe(struct platform_device *pdev)
|
||||
rga->cmdbuf_virt = dma_alloc_attrs(rga->dev, RGA_CMDBUF_SIZE,
|
||||
&rga->cmdbuf_phy, GFP_KERNEL,
|
||||
DMA_ATTR_WRITE_COMBINE);
|
||||
if (!rga->cmdbuf_virt) {
|
||||
ret = -ENOMEM;
|
||||
goto rel_vdev;
|
||||
}
|
||||
|
||||
rga->src_mmu_pages =
|
||||
(unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
|
||||
if (!rga->src_mmu_pages) {
|
||||
ret = -ENOMEM;
|
||||
goto free_dma;
|
||||
}
|
||||
rga->dst_mmu_pages =
|
||||
(unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
|
||||
if (rga->dst_mmu_pages) {
|
||||
ret = -ENOMEM;
|
||||
goto free_src_pages;
|
||||
}
|
||||
|
||||
def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
|
||||
def_frame.size = def_frame.stride * def_frame.height;
|
||||
@ -894,7 +906,7 @@ static int rga_probe(struct platform_device *pdev)
|
||||
ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
|
||||
if (ret) {
|
||||
v4l2_err(&rga->v4l2_dev, "Failed to register video device\n");
|
||||
goto rel_vdev;
|
||||
goto free_dst_pages;
|
||||
}
|
||||
|
||||
v4l2_info(&rga->v4l2_dev, "Registered %s as /dev/%s\n",
|
||||
@ -902,10 +914,15 @@ static int rga_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
|
||||
free_dst_pages:
|
||||
free_pages((unsigned long)rga->dst_mmu_pages, 3);
|
||||
free_src_pages:
|
||||
free_pages((unsigned long)rga->src_mmu_pages, 3);
|
||||
free_dma:
|
||||
dma_free_attrs(rga->dev, RGA_CMDBUF_SIZE, rga->cmdbuf_virt,
|
||||
rga->cmdbuf_phy, DMA_ATTR_WRITE_COMBINE);
|
||||
rel_vdev:
|
||||
video_device_release(vfd);
|
||||
unreg_video_dev:
|
||||
video_unregister_device(rga->vfd);
|
||||
unreg_v4l2_dev:
|
||||
v4l2_device_unregister(&rga->v4l2_dev);
|
||||
err_put_clk:
|
||||
|
Loading…
Reference in New Issue
Block a user