Просмотр исходного кода

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 <[email protected]>
Karthik Anantha Ram 2 лет назад
Родитель
Сommit
167437bdeb
2 измененных файлов с 22 добавлено и 2 удалено
  1. 3 2
      drivers/cam_sync/cam_sync.c
  2. 19 0
      drivers/cam_sync/cam_sync_dma_fence.c

+ 3 - 2
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 */

+ 19 - 0
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",