# DF-4608 — radeon_vce_cs_reloc() NULL-deref panic: CS submitted without a relocation chunk

**File:** `sys/dev/drm/radeon/radeon_vce.c` (pass 2)
**Severity:** Medium (deterministic local kernel panic from unprivileged DRM access) **Confidence:** certain
**CWE:** CWE-476

## The path

A `DRM_IOCTL_RADEON_CS` submission is parsed by `radeon_cs_parser_init()`
(radeon_cs.c:302-361): it sets `p->chunk_relocs` **only if** the user
supplied a `RADEON_CHUNK_ID_RELOCS` chunk (radeon_cs.c:313-315) — omitting
the chunk is perfectly legal. `radeon_cs_parser_relocs()`
(radeon_cs.c:83-85) then returns 0 ("nothing to do") **instead of
rejecting**, and `p->relocs`/`p->chunk_relocs` stay NULL
(the parser was memset in radeon_cs_ioctl, radeon_cs.c:674).

Selecting a VCE ring (FLAGS chunk dword 1 = `RADEON_CS_RING_VCE`, no
`RADEON_CS_USE_VM`) dispatches `radeon_vce_cs_parse`
(radeon_asic.c:1769/2077). Its very first reloc-bearing command — e.g.
`0x05000005` feedback buffer (radeon_vce.c:646-651) — calls
`radeon_vce_cs_reloc()`:

    relocs_chunk = p->chunk_relocs;                       /* NULL */
    offset = radeon_get_ib_value(p, lo);
    idx = radeon_get_ib_value(p, hi);
    if (idx >= relocs_chunk->length_dw) {                  /* NULL deref */

→ kernel page fault at `offsetof(struct radeon_cs_chunk, length_dw)` →
panic. Any local user with the DRM node open (typically unprivileged
`/dev/dri/renderD128` on desktops) can panic the machine, deterministically,
with a single ioctl.

## The guards everyone else has (and VCE forgot)

* generic packet path `radeon_cs_packet_next_reloc()` —
  radeon_cs.c:846-850: `if (p->chunk_relocs == NULL) { DRM_ERROR("No
  relocation chunk !"); return -EINVAL; }`
* UVD parser `radeon_uvd_cs_parse()` — radeon_uvd.c:705-709: the identical
  guard, at the head of the parser.

`radeon_vce_cs_parse()`/`radeon_vce_cs_reloc()` have no such check anywhere
— a plain oversight when VCE support was ported.

## Trigger

`vce_null_relocs.c`: raw ioctl (no libdrm), FLAGS chunk selecting the VCE
ring + IB chunk containing a session command followed by a feedback-buffer
command, and deliberately no RELOCS chunk.

## Guest status

Builds clean with the guest cc 8.3. The audit QEMU guest has no radeon GPU
(`ls /dev/dri` → absent; `pciconf -l | grep 1002` → zero matches), so the
ioctl cannot be exercised — trigger provided for affected hardware
(TAHITI/PITCAIRN/VERDE/OLAND/ARUBA/BONAIRE/KAVERI/KABINI/HAWAII/MULLINS
with `radeonkms` loaded and the VCE rings up).

## Fix

Mirror the UVD guard at the head of `radeon_vce_cs_parse()` (fix.diff).
