DF-5089 / verdict.json
{ "finding_id": "DF-5089", "status": "untested", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "si_copy_dma() discards the return values of radeon_sync_resv() (si_dma.c:255) and radeon_sync_rings() (si_dma.c:256) \u2014 the SI twin of DF-4871 (r600_dma.c:466-467), cross-referenced by DF-4871s own verdict and the r600 pass-2 task_log. radeon_sync_rings() fails with -EINVAL when a source ring was disabled (radeon_sync.c:153-156, reachable after a failed ib test / GPU reset) and on semaphore-create/ring-alloc/interrupted-manual-wait errors (:158-193); radeon_sync_resv() propagates interrupted dma_fence_wait() on foreign resv fences (radeon_sync.c:106,119). On failure the copy packets are still emitted and committed (si_dma.c:258-279), so the DMA copy runs unordered w.r.t. a pending write on the same bo \u2014 silent GPU-side corruption of the migrated bos contents under a healthy fence. The checked-and-unwind pattern exists in the sibling caller radeon_ib_schedule() (radeon_ib.c:149-154). Runtime verification is hardware-gated (needs real SI hardware in a degraded state; guest is QEMU std-VGA, 0 drm modules, no /dev/dri \u2014 env.txt); hardware-gated Low, per contract PoC-skippable, recorded untested (persist enum has no not_testable). Impact ceiling: unprivileged-triggerable bo content corruption on degraded hardware (I:L); no kernel memory corruption.", "exploit_chain": "", "evidence": "findings/poc/DF-5089/VERDICT.md (trace: radeon_ttm.c radeon_move_bl -> si_dma.c:244-279 -> radeon_sync.c:89-199 failure modes -> unchecked commit at :279; contrast radeon_ib.c:149-154; plus full pass-2 negative-result table for the rest of si_dma.c); env.txt (hardware gate); fix.diff (mirrors accepted DF-4871 fix shape)", "kernel_refs": [ "sys/dev/drm/radeon/si_dma.c:255", "sys/dev/drm/radeon/si_dma.c:256", "sys/dev/drm/radeon/radeon_sync.c:153", "sys/dev/drm/radeon/radeon_sync.c:160", "sys/dev/drm/radeon/radeon_sync.c:172", "sys/dev/drm/radeon/radeon_ib.c:149", "sys/dev/drm/radeon/radeon.h:628" ], "poc_changes": "n/a \u2014 no PoC seed; no deterministic userland trigger without SI-class hardware in a degraded state", "attempts": 1, "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": 15, "guest_dirty": 0, "build_cmd": "", "run_cmd": "dfbsd-qemu/vm.sh run_root uname -a; pciconf -l | grep -i vga; kldstat | grep -ci \"radeon\\|drm\"; ls /dev/dri (env probe \u2014 run.log/env.txt)", "code_hash": "", "notes": "DB check requested by orchestrator: DF-4870/4871 were filed on r600_dma.c only (not evergreen/si) \u2014 si_dma.c gets its own twin here per the r600 pass-2 task_log flag. Sibling ignored-return sites for other files audits: evergreen_dma.c:130-131, cik.c:3695-3696. Pass-2 negatives with weight: vm_*_pages chunk math exact + 20-bit packet fields (sid.h:1853-1866); IB estimates dominate emissions on all four wrapper paths (radeon_vm.c:359-379, 971-994, 653-656); ring circular + alloc-checked (radeon_ring.c:125-137, radeon.h:2708-2720) so the num_loops*5+11 slack shortfall for >=2 semaphore waits is only DRM_ERROR spam; vm_id bounded [1,15] (si.c:4787, radeon_vm.c:195-217); no fill function exists in this file; DF-2091 (>=4GB truncation) known and not re-reported.", "recommended_fix": "Check radeon_sync_resv()/radeon_sync_rings() returns in si_copy_dma() and unwind (unlock_undo + sync_free + ERR_PTR) on failure, moving sync_resv before radeon_ring_lock() \u2014 mirror of the accepted DF-4871 fix", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored from line-accurate source reading, mirroring the accepted DF-4871 fix shape and the checked sibling (radeon_ib.c:149-154); kernel fix-build validation impossible on this guest \u2014 no SI hardware to drive the DMA migration path", "fix_evidence": "findings/poc/DF-5089/fix.diff" } |