VCN rings ship with zero CS ib validation β no .parse_cs hook, userspace decode messages (session handle, fb buffer addresses/sizes) reach firmware unvalidated
Summary
amdgpu_cs validates ib contents only for rings whose funcs set .parse_cs; every UVD and VCE ring in this tree carries one but none of the three VCN ring tables does (this snapshot predates upstream's amdgpu_vcn_cs_parse/amdgpu_vcn_dec_cs_msg backport). A render-node user on a Raven APU submits a VCN IB whose embedded decode message names an arbitrary session handle and fb_buffer addresses never checked against the CS bo list - buffers absent from the list are unpinned, so TTM eviction can relocate them mid-execution while firmware still DMAs through the stale GPUVA: racy cross-process VRAM corruption; malformed fields give a reliable GPU-hang DoS. Statically certain (grep-provable); no AMD GPU on guest. Backport-the-upstream-validation fix direction.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4566 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.2 KB | β raw | |
| VERDICT.md | β | 4.5 KB | β raw | |
| static_proof.txt | β | 3.9 KB | view raw | |
| verdict.json | β | 3.3 KB | view raw | |
| manifest.json | β | 944 B | view raw |
DF-4566 β VCN rings have zero CS ib validation (no .parse_cs hook)
What this is
A static, code-provable finding: every UVD and VCE ring in this DragonFly
tree carries a kernel-side ib parser (.parse_cs), but none of the three VCN
rings does. As a result, userspace-submitted VCN decode/encode/jpeg indirect
buffers β including the firmware decode message with its session handle and
frame-buffer (fb) address/size tables β reach the VCN firmware with no
kernel validation whatsoever.
Build / Run
Not applicable β this is an absence-of-validation defect on AMD Raven (VCN)
hardware. The audit QEMU guest runs X86_64_GENERIC with no AMD GPU and no
/dev/dri (verified: ls /dev/dri β No such file or directory), so a GPU
command-submission PoC cannot be executed there. See VERDICT.md for the
static proof and static_proof.txt for the raw excerpts.
Expected result (on real Raven hardware)
A render-node client submits a decode ib whose message references a buffer
that is NOT in the CS bo list (or a session handle that was never created);
upstream Linux rejects this in amdgpu_vcn_dec_cs_msg() β this tree accepts
it silently and the firmware dereferences it.
DF-4566 VERDICT β VCN rings ship without any CS ib parser
Status: untested (dynamically), certain (statically). Impact demonstrated: none (hardware absent); defect existence: proven by inspection.
What was verified and how
The audited file is sys/dev/drm/amd/amdgpu/amdgpu_vcn.c (905 LOC, pass 2).
The pass-1 context expected a VCN decode-message parser
(amdgpu_vcn_dec_cs_msg / amdgpu_vcn_cs_parse) to exist in this file. It
does not exist anywhere in this tree β verified by
rg -n "amdgpu_vcn_(cs_parse|dec_cs_msg)" sys/ β no matches (see
static_proof.txt). This snapshot is ~Linux-4.17/4.18-vintage amdgpu (VCN 1.0,
Raven-only, sys/dev/drm/amd/amdgpu/amdgpu_vcn.c:65-76); upstream Linux added
the VCN ib check (amdgpu_vcn_cs_parse / amdgpu_vcn_dec_cs_msg, wired as
.parse_cs on the VCN dec ring) only in the ~5.1 era. The tree never got it.
Why this is a security gap, not just a missing feature
-
amdgpu_cs.c:833-836runs the whole "ib contents" path only whenring->funcs->parse_cs || ring->funcs->patch_cs_in_place(the code comment itself says "Only for UVD/VCE VM emulation"). All three VCN ring func tables βvcn_v1_0_dec_ring_vm_funcs(vcn_v1_0.c:2043-2069),vcn_v1_0_enc_ring_vm_funcs(2076-2101) andvcn_v1_0_jpeg_ring_vm_funcs(2103-2135) β set neither hook. Every UVD ring (uvd_v4_2.c:756,uvd_v5_0.c:865,uvd_v6_0.c:1530) and every VCE ring (vce_v2_0.c:615,vce_v3_0.c:902,vce_v4_0.c:1077) in the same tree does set one β the asymmetry is the defect. -
Consequence: a local user with render-node access on Raven APUs (0x1002:0x15dd / 0x15d8,
amdgpu_drv.c:911-912) submits anAMDGPU_CHUNK_ID_IBtargeting a VCN ring whose embedded decode message contains an arbitrary session handle and arbitrary fb-buffer addresses and sizes. Nothing checks that (a) the handle was created (cf.amdgpu_uvd.csession handling / DF-1657 family), or (b) each fb_buffer address corresponds to a GEM object in the validated CS bo list with adequate size (the job upstream'samdgpu_vcn_dec_cs_msgperforms for H264/HEVC messages). -
Addressing model (severity limiter): unlike pre-VM UVD (DF-4404: physical addressing), VCN 1.0 runs the ib under the submitting VM's page tables β the dec ring programs
mmUVD_LMI_RBC_IB_VMIDwith the submitter's vmid (vcn_v1_0.c:1372-1378; jpegmmUVD_LMI_JPEG_VMIDvcn_v1_0.c:1736-1741). So raw msg addresses can only name mappings the attacker already owns; the kernel-integrity angle is the bo-list/pinning divergence: buffers named in the message but absent from the CS bo list are not pinned/reserved for the job, so TTM may evict/relocate them while the firmware still DMAs through them β cross-process VRAM corruption (racy), plus unaccounted session handles and trivial GPU-hang DoS. That is why this is Medium, not High.
Why not reproduced on the guest
The audit QEMU guest (DragonFly dfbsd 6.5-DEVELOPMENT ... X86_64_GENERIC,
verified 2026-09-21) has no AMD GPU and no /dev/dri; amdgpu cannot even
load, and no VCN ring exists to submit to. Building the PoC is therefore
impossible on the available target β not a code-path refutation (the cited
path is trivially reachable on any Raven APU with the amdgpu KMD bound).
Classification mapping
- Defect existence: certain (grep-provable absence; ring-func tables cited).
- PoC status per audit status set:
untested(no hardware target exists in the harness; nothing was built or run). - Demonstrated impact:
none(no runtime demonstration possible).
Recommended fix
Backport upstream's VCN dec ib validation (amdgpu_vcn_cs_parse /
amdgpu_vcn_dec_cs_msg, incl. its follow-up bounds fixes on the fb-buffer
count for H264/HEVC messages) and wire .parse_cs = amdgpu_vcn_ring_parse_cs
into vcn_v1_0_dec_ring_vm_funcs. A full parser backport is ~200 lines from
upstream; it is not authored here because verification on real hardware was
not possible, and per audit rules fix.diff accompanies reproduced
memory-corruption findings.
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
(No fix.diff for this item: documented recommendation only - see Fix above.)
Fix verification
not_testableFix validation impossible: no AMD GPU on the verification guest, and the bug itself was not reproduced at runtime (status untested). fix.diff intentionally not authored (audit rule: fix.diff accompanies reproduced memory-corruption findings).
VERDICT.md section 'Recommended fix'; guest runtime check in notes
Confirmed kernel references
Detail
Exploit chain
on real Raven APU: open render node -> AMDGPU_CS with AMDGPU_CHUNK_ID_IB on VCN dec ring -> ib embeds crafted decode msg whose fb_buffer_address[] names a mapping absent from the CS bo list (or oversized vs bo) -> job runs without reservation/pinning -> TTM eviction relocates the buffer mid-exec -> firmware DMAs through stale GPUVA -> cross-process VRAM corruption (racy); unconditional variant: bogus session handle / msg fields -> firmware fault -> GPU hang (DoS). Not runnable on the QEMU guest (no AMD GPU).
Evidence (decisive lines)
static_proof.txt (rg output: parse_cs present on all uvd/vce rings, absent on all vcn rings; vcn_v1_0.c:2043-2069 ring funcs; amdgpu_cs.c:832-838 gate); VERDICT.md (full narrative incl. VM-addressing severity limiter, vcn_v1_0.c:1372-1378)
PoC changes
n/a β no PoC was seeded or run; finding is proven by code inspection (grep + ring func tables)
Verified recommended fix
Backport upstream amdgpu_vcn_cs_parse/amdgpu_vcn_dec_cs_msg (H264/HEVC message validation: session handle + fb_buffer address/size vs CS bo list) and set .parse_cs on vcn_v1_0_dec_ring_vm_funcs
Verdict
Statically proven: none of the three VCN ring func tables (vcn_v1_0.c:2043-2135) sets .parse_cs/.patch_cs_in_place, so amdgpu_cs.c:833-836 skips ib-contents validation entirely for VCN β userspace decode messages (session handle, fb buffer addresses/sizes) reach firmware unvalidated, unlike every UVD/VCE ring in the same tree. Dynamically untestable: the audit QEMU guest (X86_64_GENERIC) has no AMD GPU and no /dev/dri, so no PoC could be built or run; the defect is an absence provable by inspection, impact chain (bo-list pinning divergence -> cross-process VRAM corruption; session-handle spoofing; GPU hang) reasoned but not demonstrated.
No comments yet.