Commit e58430e1 authored by Dan Carpenter's avatar Dan Carpenter Committed by Mauro Carvalho Chehab
Browse files

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: f7e7b48e ("[media] rockchip/rga: v4l2 m2m support")
Reported-by: default avatarDongliang Mu <mudongliangabcd@gmail.com>
Signed-off-by: default avatarDan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 055d2db2
Loading
Loading
Loading
Loading
+22 −5
Original line number Diff line number Diff line
@@ -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: