diff --git a/sys/dev/drm/amd/amdgpu/amdgpu_ctx.c b/sys/dev/drm/amd/amdgpu/amdgpu_ctx.c --- a/sys/dev/drm/amd/amdgpu/amdgpu_ctx.c +++ b/sys/dev/drm/amd/amdgpu/amdgpu_ctx.c @@ -442,18 +442,25 @@ struct dma_fence *fence, uint64_t* handle) { struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity); - uint64_t seq = centity->sequence; + uint64_t seq; struct dma_fence *other = NULL; unsigned idx = 0; + dma_fence_get(fence); + + /* + * DF-1863: claim the slot atomically with the write. Reading + * centity->sequence / fences[idx] OUTSIDE the lock allowed two + * concurrent CS ioctl callers to observe the same `other` fence and + * both dma_fence_put() it, producing a double-free / UAF on the prior + * slot's drm_sched_fence (and leaking the loser's just-stored fence). + */ + lockmgr(&ctx->ring_lock, LK_EXCLUSIVE); + seq = centity->sequence; idx = seq & (amdgpu_sched_jobs - 1); other = centity->fences[idx]; if (other) BUG_ON(!dma_fence_is_signaled(other)); - - dma_fence_get(fence); - - lockmgr(&ctx->ring_lock, LK_EXCLUSIVE); centity->fences[idx] = fence; centity->sequence++; lockmgr(&ctx->ring_lock, LK_RELEASE);