# DF-4264 — `AMDGPU_FENCE_TO_HANDLE` default case leaks the dma_fence reference

**File:** `sys/dev/drm/amd/amdgpu/amdgpu_cs.c` (pass 2)
**Severity:** Low (unprivileged kernel memory leak / slow DoS) — CWE-401
**Confidence:** certain

## Build

```
cc -O2 -Wall -o fence_to_handle_leak fence_to_handle_leak.c
```

## Run (as any user on amdgpu hardware)

```
./fence_to_handle_leak
```
Allocates a context, submits one GFX CS (so the context records fence
seq 1), then issues 10 000 `DRM_IOCTL_AMDGPU_FENCE_TO_HANDLE` calls with
`in.what = 0xFFFFFFFF`. Every call leaks one `dma_fence` reference.

## Root cause (path:line)

`amdgpu_cs_fence_to_handle_ioctl()` (amdgpu_cs.c:1417-1471) takes the
fence reference at :1427 (`amdgpu_cs_get_fence` →
`amdgpu_ctx_get_fence`, amdgpu_ctx.c:489 takes a `dma_fence_get`). The
three valid `what` cases each `dma_fence_put()` the reference
(:1434/:1343-1447, :1453/:1458, :1464); the **default** case
(:1468-1470) returns `-EINVAL` **without** the put. Each invalid call
permanently keeps alive a `drm_sched_fence` slab object and, through the
parent chain, everything the release path would have dropped.

Reachability: `AMDGPU_FENCE_TO_HANDLE` is `DRM_AUTH|DRM_RENDER_ALLOW`
(amdgpu_kms.c:1202).

## Guest verification (this audit)

Same hardware gate as DF-4262 (no AMD GPU → no `/dev/dri`): trigger
builds (`build.log`), run exits at open (`run.log`); baseline + patched
in-tree compile of `amdgpu_cs.c` rc=0 with `-Werror`
(`kmod_baseline_build.log`, `fix_build.log` — the one-line fix adds
`dma_fence_put(fence);` before the `-EINVAL` return).

## Fix

`fix.diff`: `default: dma_fence_put(fence); return -EINVAL;`
