From 167437bdeb700845eb42195dbd1535c170d55de1 Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Mon, 29 Aug 2022 21:39:30 -0700 Subject: [PATCH] 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 --- drivers/cam_sync/cam_sync.c | 5 +++-- drivers/cam_sync/cam_sync_dma_fence.c | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/cam_sync/cam_sync.c b/drivers/cam_sync/cam_sync.c index fed4022d67..2eb5f74229 100644 --- a/drivers/cam_sync/cam_sync.c +++ b/drivers/cam_sync/cam_sync.c @@ -1079,8 +1079,9 @@ static int cam_generic_fence_handle_dma_release( rc = cam_dma_fence_release(&release_params); if (rc) { CAM_ERR(CAM_DMA_FENCE, - "Failed to destroy dma fence at index: %d rc: %d num fences [requested: %u processed: %u]", - i, rc, fence_input_info->num_fences_requested, + "Failed to destroy dma fence at index: %d fd: %d rc: %d num fences [requested: %u processed: %u]", + i, fence_cfg->dma_fence_fd, rc, + fence_input_info->num_fences_requested, fence_input_info->num_fences_processed); fence_cfg->reason_code = rc; /* Continue to release other fences, but mark the call as failed */ diff --git a/drivers/cam_sync/cam_sync_dma_fence.c b/drivers/cam_sync/cam_sync_dma_fence.c index 8e68d115c4..5f2093478c 100644 --- a/drivers/cam_sync/cam_sync_dma_fence.c +++ b/drivers/cam_sync/cam_sync_dma_fence.c @@ -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]); 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) { spin_unlock_bh(&g_cam_dma_fence_dev->row_spinlocks[idx]); 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]; 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) { CAM_WARN(CAM_DMA_FENCE, "Unsignaled fence being released name: %s seqno: %llu fd:%d",