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)) {
|
if (IS_ERR(rga->m2m_dev)) {
|
||||||
v4l2_err(&rga->v4l2_dev, "Failed to init mem2mem device\n");
|
v4l2_err(&rga->v4l2_dev, "Failed to init mem2mem device\n");
|
||||||
ret = PTR_ERR(rga->m2m_dev);
|
ret = PTR_ERR(rga->m2m_dev);
|
||||||
goto unreg_video_dev;
|
goto rel_vdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = pm_runtime_resume_and_get(rga->dev);
|
ret = pm_runtime_resume_and_get(rga->dev);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto unreg_video_dev;
|
goto rel_vdev;
|
||||||
|
|
||||||
rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
|
rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
|
||||||
rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
|
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_virt = dma_alloc_attrs(rga->dev, RGA_CMDBUF_SIZE,
|
||||||
&rga->cmdbuf_phy, GFP_KERNEL,
|
&rga->cmdbuf_phy, GFP_KERNEL,
|
||||||
DMA_ATTR_WRITE_COMBINE);
|
DMA_ATTR_WRITE_COMBINE);
|
||||||
|
if (!rga->cmdbuf_virt) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto rel_vdev;
|
||||||
|
}
|
||||||
|
|
||||||
rga->src_mmu_pages =
|
rga->src_mmu_pages =
|
||||||
(unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
|
(unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
|
||||||
|
if (!rga->src_mmu_pages) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto free_dma;
|
||||||
|
}
|
||||||
rga->dst_mmu_pages =
|
rga->dst_mmu_pages =
|
||||||
(unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
|
(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.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
|
||||||
def_frame.size = def_frame.stride * def_frame.height;
|
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);
|
ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
v4l2_err(&rga->v4l2_dev, "Failed to register video device\n");
|
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",
|
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;
|
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:
|
rel_vdev:
|
||||||
video_device_release(vfd);
|
video_device_release(vfd);
|
||||||
unreg_video_dev:
|
|
||||||
video_unregister_device(rga->vfd);
|
|
||||||
unreg_v4l2_dev:
|
unreg_v4l2_dev:
|
||||||
v4l2_device_unregister(&rga->v4l2_dev);
|
v4l2_device_unregister(&rga->v4l2_dev);
|
||||||
err_put_clk:
|
err_put_clk:
|
||||||
|
Loading…
Reference in New Issue
Block a user