DF-4871 / verdict.json
{ "finding_id": "DF-4871", "status": "untested", "reproduced": 0, "impact": "none", "confidence": "likely", "verdict": "r600_copy_dma() discards the return values of radeon_sync_resv() (r600_dma.c:466) and radeon_sync_rings() (r600_dma.c:467). radeon_sync_rings() can fail with -EINVAL when a source ring was disabled (radeon_sync.c:153-156, reachable after a failed ib test sets ring->ready=false per radeon_ib.c:271) or on fence-wait errors; on failure the copy packets are still emitted and committed (r600_dma.c:469-490), so the DMA copy runs unordered w.r.t. a pending write on the same bo \u2014 silent GPU-side data corruption of the migrated buffers own contents. Sibling caller radeon_ib_schedule() checks the identical call and unwinds (radeon_ib.c:149-154), and upstream Linux checks radeon_sync_resv() in this exact function \u2014 this tree diverges. Runtime verification is hardware-gated (needs real r6xx+ hardware in a degraded state); the audit guest has only Bochs VGA, no /dev/dri, no radeon.ko (env.txt). Impact ceiling: unprivileged-triggerable bo content corruption on degraded hardware (I:L); no kernel memory corruption.", "exploit_chain": "", "evidence": "findings/poc/DF-4871/VERDICT.md (trace: radeon_ttm.c:302 radeon_copy -> r600_dma.c:466-467 -> radeon_sync.c:137-201 failure modes -> unchecked commit at r600_dma.c:490; contrast radeon_ib.c:149-154); env.txt (hardware gate); fix.diff (checks both returns, unwinds, moves sync_resv before the ring lock per upstream)", "kernel_refs": [ "sys/dev/drm/radeon/r600_dma.c:466", "sys/dev/drm/radeon/r600_dma.c:467", "sys/dev/drm/radeon/radeon_sync.c:153", "sys/dev/drm/radeon/radeon_sync.c:160", "sys/dev/drm/radeon/radeon_ib.c:149", "sys/dev/drm/radeon/radeon_ttm.c:302" ], "poc_changes": "n/a \u2014 no PoC seed existed; no deterministic userland trigger (needs degraded real hardware)", "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": 12, "guest_dirty": 0, "build_cmd": "", "run_cmd": "dfbsd-qemu/vm.sh run_root pciconf -l; kldstat; ls /dev/dri (env probe \u2014 see run.log/env.txt)", "code_hash": "", "notes": "Hardware-gated Low finding; per contract Phase V skippable for Low \u2014 recorded as untested (persist_poc enum). Identical ignored-return pattern exists in evergreen_dma.c:130-131, rv770_dma.c:66-67, si_dma.c:255-256, r600.c:2997-2998 (cross-refs for the orchestrator; fixes belong in those files own audits). resv is always the embedded &bo->tbo.resv on this path, so the upstream NULL-resv crash variant does not apply. Not a duplicate of DF-1942 (size math) or DF-1943 (reservation size): orthogonal ignored-error defect.", "recommended_fix": "Check the radeon_sync_resv()/radeon_sync_rings() returns in r600_copy_dma() and unwind (unlock_undo + sync_free + ERR_PTR) on failure, moving sync_resv before radeon_ring_lock()", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored from line-accurate source reading, mirroring the checked sibling (radeon_ib.c:149-154) and upstream Linux structure; kernel fix-build validation impossible on this guest \u2014 no Radeon hardware to drive the copy path", "fix_evidence": "findings/poc/DF-4871/fix.diff" } |