msm: camera: sync: Avoid use after free

There is a narrow window, in which the critical section is
not fully protected which possibly could lead to use after free.
To avoid this, hold the row lock and validate the state prior
to processing the dma fence.

CRs-Fixed: 3273450
Change-Id: Ib1f09e62a5060a38b5cd8f3d4594bce2e533b3d3
Signed-off-by: Karthik Anantha Ram <quic_kartanan@quicinc.com>
This commit is contained in:
Karthik Anantha Ram
2022-08-29 21:39:30 -07:00
committed by Camera Software Integration
parent 53d149b019
commit 167437bdeb
2 changed files with 22 additions and 2 deletions

View File

@@ -1079,8 +1079,9 @@ static int cam_generic_fence_handle_dma_release(
rc = cam_dma_fence_release(&release_params); rc = cam_dma_fence_release(&release_params);
if (rc) { if (rc) {
CAM_ERR(CAM_DMA_FENCE, CAM_ERR(CAM_DMA_FENCE,
"Failed to destroy dma fence at index: %d rc: %d num fences [requested: %u processed: %u]", "Failed to destroy dma fence at index: %d fd: %d rc: %d num fences [requested: %u processed: %u]",
i, rc, fence_input_info->num_fences_requested, i, fence_cfg->dma_fence_fd, rc,
fence_input_info->num_fences_requested,
fence_input_info->num_fences_processed); fence_input_info->num_fences_processed);
fence_cfg->reason_code = rc; fence_cfg->reason_code = rc;
/* Continue to release other fences, but mark the call as failed */ /* Continue to release other fences, but mark the call as failed */

View File

@@ -421,6 +421,18 @@ int cam_dma_fence_signal_fd(struct cam_dma_fence_signal *signal_dma_fence)
spin_lock_bh(&g_cam_dma_fence_dev->row_spinlocks[idx]); spin_lock_bh(&g_cam_dma_fence_dev->row_spinlocks[idx]);
row = &g_cam_dma_fence_dev->rows[idx]; row = &g_cam_dma_fence_dev->rows[idx];
/*
* Check for invalid state again, there could be a contention
* between signal and release
*/
if (row->state == CAM_DMA_FENCE_STATE_INVALID) {
spin_unlock_bh(&g_cam_dma_fence_dev->row_spinlocks[idx]);
CAM_ERR(CAM_DMA_FENCE,
"dma fence fd: %d is invalid row_idx: %u, failed to signal",
signal_dma_fence->dma_fence_fd, idx);
return -EINVAL;
}
if (row->state == CAM_DMA_FENCE_STATE_SIGNALED) { if (row->state == CAM_DMA_FENCE_STATE_SIGNALED) {
spin_unlock_bh(&g_cam_dma_fence_dev->row_spinlocks[idx]); spin_unlock_bh(&g_cam_dma_fence_dev->row_spinlocks[idx]);
CAM_WARN(CAM_DMA_FENCE, CAM_WARN(CAM_DMA_FENCE,
@@ -535,6 +547,13 @@ static int __cam_dma_fence_release(int32_t dma_row_idx)
row = &g_cam_dma_fence_dev->rows[dma_row_idx]; row = &g_cam_dma_fence_dev->rows[dma_row_idx];
dma_fence = row->fence; dma_fence = row->fence;
if (row->state == CAM_DMA_FENCE_STATE_INVALID) {
spin_unlock_bh(&g_cam_dma_fence_dev->row_spinlocks[dma_row_idx]);
CAM_ERR(CAM_DMA_FENCE, "Invalid row index: %u, state: %u",
dma_row_idx, row->state);
return -EINVAL;
}
if (row->state == CAM_DMA_FENCE_STATE_ACTIVE) { if (row->state == CAM_DMA_FENCE_STATE_ACTIVE) {
CAM_WARN(CAM_DMA_FENCE, CAM_WARN(CAM_DMA_FENCE,
"Unsignaled fence being released name: %s seqno: %llu fd:%d", "Unsignaled fence being released name: %s seqno: %llu fd:%d",