⬢ DragonFlyBSD Kernel Audit
DF-4447 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4447",
  "status": "untested",
  "reproduced": 0,
  "impact": "dos",
  "confidence": "likely",
  "verdict": "Two-pass desynchronization in amdgpu_vce_ring_parse_cs: loop 2 re-reads len/cmd from IB dwords that amdgpu_vce_cs_reloc patched in the same pass. A buffer command (0x05000001/04/05/0d) with len=8 has its patched address dwords (idx+2=upper32, idx+3=lower32 of final) land exactly on the NEXT commands len/cmd header; the attacker arranges final=(len<<32)|no-op-cmd with len in 0..3 so idx += len/4 never advances, producing an infinite in-kernel loop inside the CS ioctl (unkillable CPU burn per submission) and letting post-desync synthesized commands skip the loop-1 validation pass entirely. Reachable unprivileged via /dev/dri/renderD128 on CIK/Tonga/Fiji (vce_v2_0 .parse_cs). Mechanism proven by dword-level trace (VERDICT.md); execution impossible on the audit guest (no AMD GPU). Distinct from DF-1625/1626/1627 (in-IB aliasing vs IB-end OOB; no size overflow; no 1<<-1). Still unfixed in Linux v6.6.",
  "exploit_chain": "",
  "evidence": "findings/poc/DF-4447/VERDICT.md (line trace); vce_cs_desync.c (dword-exact trigger: session cmd, len=8 bitstream cmd whose idx+2/idx+3 are the next header, delta sweep); amdgpu_vce.c:656-657 (patch writes), :791-792+914 (loop-2 re-read + idx advance with no len check), :728 (len check only in loop 1)",
  "kernel_refs": [
    "sys/dev/drm/amd/amdgpu/amdgpu_vce.c:790",
    "sys/dev/drm/amd/amdgpu/amdgpu_vce.c:656",
    "sys/dev/drm/amd/amdgpu/amdgpu_vce.c:877",
    "sys/dev/drm/amd/amdgpu/amdgpu_vce.c:914",
    "sys/dev/drm/amd/amdgpu/vce_v2_0.c:615",
    "sys/dev/drm/amd/amdgpu/cik.c:2024"
  ],
  "poc_changes": "n/a (first evidence pack for this finding; trigger authored from scratch against the DF amdgpu source, raw ioctls, no libdrm dependency)",
  "attempts": 0,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0 Thu Jul 2 2026 x86_64 (guest has no AMD GPU: pciconf shows no 1002: device, /dev/dri absent)",
  "runtime_sec": 0,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -o vce_cs_desync vce_cs_desync.c",
  "run_cmd": "./vce_cs_desync /dev/dri/renderD128",
  "code_hash": "64fcb46ebbfbdca5008a5f697d2daf2ff45eb456f43c186f02316676bc310782",
  "notes": "Hardware-required finding (AMD GPU with vce_v2_0 IP block); QEMU guest lacks the device, so no execution attempt was possible \u2014 status untested per audit precedent (cf. DF-4431). Upstream v6.6 carries the same two-loop structure and unbounded patch offsets: novel, upstream-affecting. The len<8/len&3 floors in fix.diff also harden the loop-2 walk itself; IB-end OOB (DF-1626) needs its own idx+len/4<=length_dw check and is NOT claimed fixed here.",
  "recommended_fix": "Per-command minimum length checks covering every dword loop 2 reads or patches (see fix.diff): session 12, task info 32, create 44, encode 52, context/bitstream/feedback 16 (bitstream 20 for the idx+4 size field), MV 36, plus re-check len sanity in loop 2.",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff authored against the read-only sys/ tree (per-command length floors + len sanity re-check in loop 2). Cannot be build- or run-validated on the audit guest: no AMD GPU, amdgpu does not attach, so neither baseline nor patched kernel can execute the VCE parse path.",
  "fix_evidence": "findings/poc/DF-4447/fix.diff (git-apply-able unified diff vs sys/dev/drm/amd/amdgpu/amdgpu_vce.c); env.txt documents guest hardware absence"
}