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>
Цей коміт міститься в:
Karthik Anantha Ram
2022-08-29 21:39:30 -07:00
зафіксовано Camera Software Integration
джерело 53d149b019
коміт 167437bdeb
2 змінених файлів з 22 додано та 2 видалено

Переглянути файл

@@ -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 */

Переглянути файл

@@ -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",