⬢ DragonFlyBSD Kernel Audit
DF-5229 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5229",
  "status": "untested",
  "verdict": "uvd_v4_2_resume (sys/dev/drm/radeon/uvd_v4_2.c:46-64) programs the UVD VCPU LMI cache windows starting 512 bytes into vcpu_bo when fw_header_present (the live path for BONAIRE/KABINI/KAVERI/HAWAII/MULLINS with the preferred new-format fw, radeon_uvd.c:124-131,153) but keeps region0 sized RADEON_GPU_PAGE_ALIGN(datasize+4) for the FULL blob, while radeon_uvd.c:184-186 sizes the bo at ALIGN(datasize+8)+HEAP+STACK+SESSION*N. The contiguous window chain therefore ends at 0x200+ALIGN(ds+4)+HEAP+STACK+SESSION*N = bo_end+512 for 99.90% of fw sizes (safe only for ds%4096 in [4089..4092]). With the SHIPPING firmware (in-tree sys/contrib/dev/drm/radeonfw/bonaire_uvd.bin.uu: datasize=232752, %4096=3376, ucode 1.64 -> max_handles=30) the overhang is exactly +512 bytes (bo=0x222000, span=0x222200): the tail of the 30-handle SESSION region is GPU-mapped into the VRAM object allocated after vcpu_bo. Proven exhaustively by check_arith.py (arith.log; headerless control 0/65536 overruns, N-independence shown). Not runtime-verifiable: guest has no AMD ASIC (env.txt) and the window-tail access is fw-behavior-dependent during a real decode session -- same acceptance basis as DF-4524/DF-4742/DF-4832 (DF-4832s harness already cross-noted this exact shape). amdgpu fixed the class for the same silicon via the offset+size==fw-region invariant (amdgpu_uvd.h:32-38); radeon never got it. GPU-scope only: LMI windows map VRAM, not host memory; ceiling is 512B cross-object GPU read/write between adjacent GEM bos during video decode (CS-reachable by unprivileged users on real hw). No kernel host-memory impact; no user-controlled input in this file.",
  "reproduced": false,
  "impact": "none",
  "confidence": "speculative",
  "exploit_chain": "",
  "evidence": "arith.log (exhaustive: min=max=512B, 65472/65536 sizes vulnerable, safe residues exactly [4089..4092]; headerless control 0 overruns; shipping fw bo=0x222000 span=0x222200; post-fix span==bo_size for all sampled ds and both N); fw_header.txt (decoded shipping blob: datasize 232752, size_bytes==datasize so radeon_ucode_validate passes, ucode 1.64 -> N=30, payload offset 0x100); VERDICT.md (derivation + amdgpu divergence + negative checks); env.txt (guest: NO_AMD_PCI)",
  "kernel_refs": [
    "sys/dev/drm/radeon/uvd_v4_2.c:46",
    "sys/dev/drm/radeon/uvd_v4_2.c:51",
    "sys/dev/drm/radeon/uvd_v4_2.c:55",
    "sys/dev/drm/radeon/uvd_v4_2.c:60",
    "sys/dev/drm/radeon/radeon_uvd.c:184",
    "sys/dev/drm/radeon/radeon_uvd.c:153",
    "sys/dev/drm/radeon/radeon.h:1675",
    "sys/dev/drm/radeon/cik.c:8175",
    "sys/dev/drm/radeon/kv_dpm.c:1628",
    "sys/dev/drm/amd/amdgpu/amdgpu_uvd.h:32"
  ],
  "poc_changes": "no seed; arithmetic harness written fresh DF-4832-style (its check_arith.py already modeled v4_2_span and cross-noted the 512B shape); added the exact shipping-firmware constants decoded from the in-tree .uu blob",
  "attempts": 0,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026  root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "runtime_sec": 0,
  "guest_dirty": 0,
  "build_cmd": "python3 decode_fw.py",
  "run_cmd": "python3 check_arith.py (runtime hw-gated: needs CIK UVD GPU + bonaire fw + CS decode session)",
  "code_hash": "6647bd48e61f23f715fcb9115790a1966225710e02f9e4085181f239560fce90",
  "notes": "hw-gated (BONAIRE/KABINI/KAVERI/HAWAII/MULLINS UVD + radeonkmsfw_bonaire_uvd); radeon CIK twin of DF-4832 (128B v1) / DF-4524 / DF-4742 (256B VCE); amdgpu already fixed the class via AMDGPU_UVD_FIRMWARE_OFFSET/SIZE invariant; guest reset clean, no kernel run performed",
  "recommended_fix": "size region0 so offset0+size0 == the fw region the bo holds: when fw_header_present, size = (RADEON_GPU_PAGE_ALIGN(datasize+8) - 0x200) >> 3 (amdgpu invariant), keeping the whole window chain inside vcpu_bo",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Fix not kernel-validated: no CIK UVD GPU on this guest, no baseline to flip. fix.diff is arithmetic-exact: post-fix span == bo_size for every ds in [0,0x2FFFF] (sampled every 7 bytes) and both max_handles values; headerless branch untouched; git apply --check clean.",
  "fix_evidence": "fix.diff (git apply --check clean; window chain ends exactly at bo end); arith.log tail (fix-validation sweep)"
}