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

Commit 1824ac8e authored by Gaurav Jindal's avatar Gaurav Jindal
Browse files

msm: camera: mem: Mutex before cpu_begin_access & cpu_end_access



In corner cases, a possibility lies that ion buffer is getting freed
and simultaneously cpu_begin_access or cpu_end_access is called on
another cpu. If the buffer gets freed before dereferencing, device
will crash.
It protects the tbl.bufq[idx] with tbl.bufq[idx].q_lock.
This will prevent the parallel access of the same buffer.

Change-Id: I9e04486b5ee815b0880ccc704065182811db59cc
Signed-off-by: default avatarGaurav Jindal <gjindal@codeaurora.org>
parent 2e671e75
Loading
Loading
Loading
Loading
+45 −18
Original line number Diff line number Diff line
@@ -251,33 +251,50 @@ int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len)
	if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0)
		return -EINVAL;

	if (!tbl.bufq[idx].active)
		return -EPERM;
	mutex_lock(&tbl.bufq[idx].q_lock);
	if (!tbl.bufq[idx].active) {
		CAM_ERR(CAM_MEM, "idx: %d not active", idx);
		rc = -EPERM;
		goto end;
	}

	if (buf_handle != tbl.bufq[idx].buf_handle)
		return -EINVAL;
	if (buf_handle != tbl.bufq[idx].buf_handle) {
		CAM_ERR(CAM_MEM, "idx: %d Invalid buf handle %d",
				idx, buf_handle);
		rc = -EINVAL;
		goto end;
	}

	if (!(tbl.bufq[idx].flags & CAM_MEM_FLAG_KMD_ACCESS))
		return -EINVAL;
	if (!(tbl.bufq[idx].flags & CAM_MEM_FLAG_KMD_ACCESS)) {
		CAM_ERR(CAM_MEM, "idx: %d Invalid flag 0x%x",
					idx, tbl.bufq[idx].flags);
		rc = -EINVAL;
		goto end;
	}

	if (tbl.bufq[idx].kmdvaddr) {
		dmabuf = tbl.bufq[idx].dma_buf;
		if (!dmabuf) {
			CAM_ERR(CAM_MEM, "Invalid DMA buffer pointer");
			return -EINVAL;
			rc = -EINVAL;
			goto end;
		}
		rc = dma_buf_begin_cpu_access(dmabuf, DMA_BIDIRECTIONAL);
		if (rc) {
			CAM_ERR(CAM_MEM, "dma begin access failed rc=%d", rc);
			return rc;
			goto end;
		}
	} else {
		return -EINVAL;
		CAM_ERR(CAM_MEM, "Invalid kmdvaddr");
		rc = -EINVAL;
		goto end;
	}

	*vaddr_ptr = tbl.bufq[idx].kmdvaddr;
	*len = tbl.bufq[idx].len;

end:
	mutex_unlock(&tbl.bufq[idx].q_lock);
	return rc;
}
EXPORT_SYMBOL(cam_mem_get_cpu_buf);
@@ -300,30 +317,38 @@ int cam_mem_put_cpu_buf(int32_t buf_handle)
	if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0)
		return -EINVAL;

	if (!tbl.bufq[idx].active)
		return -EPERM;
	mutex_lock(&tbl.bufq[idx].q_lock);
	if (!tbl.bufq[idx].active) {
		CAM_ERR(CAM_MEM, "idx: %d not active", idx);
		rc = -EPERM;
		goto end;
	}

	if (buf_handle != tbl.bufq[idx].buf_handle)
		return -EINVAL;
	if (buf_handle != tbl.bufq[idx].buf_handle) {
		CAM_ERR(CAM_MEM, "idx: %d Invalid buf handle %d",
				idx, buf_handle);
		rc = -EINVAL;
		goto end;
	}

	dmabuf = tbl.bufq[idx].dma_buf;
	if (!dmabuf) {
		CAM_ERR(CAM_CRM, "Invalid DMA buffer pointer");
		return -EINVAL;
		rc = -EINVAL;
		goto end;
	}

	if ((tbl.bufq[idx].flags & CAM_MEM_FLAG_KMD_ACCESS) &&
		(tbl.bufq[idx].kmdvaddr)) {
		rc = dma_buf_end_cpu_access(dmabuf, DMA_BIDIRECTIONAL);
		if (rc) {
		if (rc)
			CAM_ERR(CAM_MEM, "dma begin access failed rc=%d", rc);
			return rc;
		}
	} else {
		CAM_ERR(CAM_MEM, "Invalid buf flag");
		rc = -EINVAL;
	}

end:
	mutex_unlock(&tbl.bufq[idx].q_lock);
	return rc;
}
EXPORT_SYMBOL(cam_mem_put_cpu_buf);
@@ -953,6 +978,7 @@ static int cam_mem_mgr_cleanup_table(void)
		tbl.bufq[i].num_hdl = 0;
		tbl.bufq[i].dma_buf = NULL;
		tbl.bufq[i].active = false;
		tbl.bufq[i].kmdvaddr = 0;
		mutex_unlock(&tbl.bufq[i].q_lock);
		mutex_destroy(&tbl.bufq[i].q_lock);
	}
@@ -1051,6 +1077,7 @@ static int cam_mem_util_unmap(int32_t idx,
	tbl.bufq[idx].len = 0;
	tbl.bufq[idx].num_hdl = 0;
	tbl.bufq[idx].active = false;
	tbl.bufq[idx].kmdvaddr = 0;
	mutex_unlock(&tbl.bufq[idx].q_lock);
	mutex_destroy(&tbl.bufq[idx].q_lock);
	clear_bit(idx, tbl.bitmap);