Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2cdb64bb authored by Govindaraj Rajagopal's avatar Govindaraj Rajagopal Committed by Gerrit - the friendly Code Review server
Browse files

msm: vidc: fix msm_comm_get_vidc_buffer fd race issue



In msm_comm_get_vidc_buffer(), we get and manipulate dma_buf
from "fd". But we dont consider the dma-buf can be freed and
recreated from userspace since fd is predictable. As such,
the dma buf we get in "msm_smem_map_dma_buf" may not be the
buffer we verified before. This could lead to type confusion
issues. So added change to hold dma_buf refcount for the
entire msm_comm_get_vidc_buffer() duration.

Change-Id: Ifce821a9a7f95ec45557f7adb1f1bb00efb0151f
Signed-off-by: default avatarGovindaraj Rajagopal <quic_grajagop@quicinc.com>
parent 870afd06
Loading
Loading
Loading
Loading
+17 −19
Original line number Diff line number Diff line
@@ -6508,25 +6508,24 @@ struct msm_vidc_buffer *msm_comm_get_vidc_buffer(struct msm_vidc_inst *inst,
	struct vb2_v4l2_buffer *vbuf;
	struct vb2_buffer *vb;
	unsigned long dma_planes[VB2_MAX_PLANES] = {0};
	struct msm_vidc_buffer *mbuf;
	struct msm_vidc_buffer *mbuf = NULL;
	bool found = false;
	int i;
	int i = 0, planes = 0;

	if (!inst || !vb2) {
		dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
		return NULL;
	}

	for (i = 0; i < vb2->num_planes; i++) {
	for (planes = 0; planes < vb2->num_planes; planes++) {
		/*
		 * always compare dma_buf addresses which is guaranteed
		 * to be same across the processes (duplicate fds).
		 */
		dma_planes[i] = (unsigned long)msm_smem_get_dma_buf(
				vb2->planes[i].m.fd);
		if (!dma_planes[i])
			return NULL;
		msm_smem_put_dma_buf((struct dma_buf *)dma_planes[i]);
		dma_planes[planes] = (unsigned long)msm_smem_get_dma_buf(
				vb2->planes[planes].m.fd);
		if (!dma_planes[planes])
			goto put_ref;
	}

	mutex_lock(&inst->registeredbufs.lock);
@@ -6614,22 +6613,21 @@ struct msm_vidc_buffer *msm_comm_get_vidc_buffer(struct msm_vidc_inst *inst,
	if (!found)
		list_add_tail(&mbuf->list, &inst->registeredbufs.list);

	mutex_unlock(&inst->registeredbufs.lock);
exit:
	if (rc == -EEXIST) {
		print_vidc_buffer(VIDC_DBG, "qbuf upon rbr", inst, mbuf);
		return ERR_PTR(rc);
	}

	return mbuf;

exit:
	} else if (rc) {
		dprintk(VIDC_ERR, "%s: rc %d\n", __func__, rc);
		msm_comm_unmap_vidc_buffer(inst, mbuf);
		if (!found)
			kref_put_mbuf(mbuf);
	}
	mutex_unlock(&inst->registeredbufs.lock);
put_ref:
	while (planes)
		msm_smem_put_dma_buf((struct dma_buf *)dma_planes[--planes]);

	return ERR_PTR(rc);
	return rc ? ERR_PTR(rc) : mbuf;
}

void msm_comm_put_vidc_buffer(struct msm_vidc_inst *inst,