[PATCH 4/5] drm/amdgpu: enforce UVD handle ownership on destroy
Junrui Luo via B4 Relay <[email protected]>
| Newsgroups | org.kernel.vger.linux-media,org.freedesktop.lists.amd-gfx,org.freedesktop.lists.dri-devel,org.kernel.feeds.b4-sent,org.kernel.vger.linux-kernel,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
From: Junrui Luo <[email protected]> amdgpu_uvd_cs_msg() validates that a decode message references a handle owned by the submitting client, rejecting a mismatch between adev->uvd.filp[i] and ctx->parser->filp. The handles[] and filp[] tables are per-device and shared by every drm_file that opens the render node. The destroy message performs no such check: it walks the whole table and clears every slot matching the handle taken from the command stream buffer. A client can therefore destroy a handle owned by another client, clearing the victim's slot and tearing down its session in UVD firmware, so subsequent decode submissions fail with -ENOENT. Since amdgpu_uvd_free_handles() only reaps slots whose handle is non-zero, the cleared slot also retains a stale filp pointer until reused. Apply the decode arm's ownership test to the destroy arm. The kunmap is hoisted above the loop, matching the create and decode arms, so the new error return cannot leak the amdgpu_bo_kmap() reference. Kernel-initiated teardown goes through amdgpu_uvd_send_msg() and never runs the parser. Fixes: 5146419e6feb ("drm/amdgpu: make UVD handle checking more strict") Reported-by: Yuhao Jiang <[email protected]> Assisted-by: Claude:claude-opus-5 Cc: [email protected] Signed-off-by: Junrui Luo <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index e8b0c62f72be..8d3e5435cf52 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -918,9 +918,19 @@ static int amdgpu_uvd_cs_msg(struct amdgpu_uvd_cs_ctx *ctx, case 2: /* it's a destroy msg, free the handle */ - for (i = 0; i < adev->uvd.max_handles; ++i) - atomic_cmpxchg(&adev->uvd.handles[i], handle, 0); amdgpu_bo_kunmap(bo); + + for (i = 0; i < adev->uvd.max_handles; ++i) { + if (atomic_read(&adev->uvd.handles[i]) != handle) + continue; + + if (adev->uvd.filp[i] != ctx->parser->filp) { + DRM_ERROR("UVD handle collision detected!\n"); + return -EINVAL; + } + + atomic_cmpxchg(&adev->uvd.handles[i], handle, 0); + } return 0; default: -- 2.51.2