DF-4713 / verdict.json
{ "finding_id": "DF-4713", "status": "untested", "reproduced": 0, "impact": "none demonstrated (hardware-gated: guest has no AMD GPU, amdgpu never binds); realistic ceiling is a hardirq NULL function-pointer call => kernel panic (local DoS) if an IH vector ever reaches a .process-less registered source (dce_virtual crtc_irq, LEGACY/229, num_types=7) or if a num_types>0 .set-less source is ever registered and the GPU-reset resume helper runs", "confidence": "likely", "verdict": "untested (runtime): amdgpu_irq_dispatch (amdgpu_irq.c:436) calls src->funcs->process and amdgpu_irq_update (amdgpu_irq.c:467) calls src->funcs->set without the NULL guards the file itself uses at :134 (disable_all), :520-521/:550-551 (get/put); amdgpu_irq_add_id (:359-360) only requires funcs != NULL, so .process-less/.set-less sources register fine. In-tree providers exist: dce_virtual_crtc_irq_funcs {.set=..., .process=NULL} (dce_virtual.c:757-760) registered with num_types=7 at LEGACY/229 (dce_virtual.c:375) - a stray/stale SMU_DISP_TIMER2 IV on a virtual-display config is a hardirq NULL-call panic; sdma illegal_inst sources have no .set but num_types==0 today, leaving amdgpu_irq_gpu_reset_resume_helper (:488-494 -> amdgpu_device.c:3287/3341) one registration away from a reset-path panic. Distinct from DF-4643 (that defect is the sleeping .set callback under the DragonFly sleepable-lockmgr shim - lock type verified here: spinlock_t == struct lock, spin_lock_irqsave == local_irq_save(crit_enter only) + lockmgr(LK_EXCLUSIVE), lockinit LK_CANRECURSE at amdgpu_irq.c:237). Fix compile-validated: full amdgpu KLD module build with -Werror, MOD_BUILD_RC=0, patched amdgpu_irq.c compiled at build.log:119.", "exploit_chain": [], "evidence": "findings/poc/DF-4713/VERDICT.md (callback-contract matrix, DF-4643 lock verification, all killed candidates incl. fini double-free and teardown ordering); build.log (full amdgpu module build, MOD_BUILD_RC=0 at :354, patched amdgpu_irq.c -Werror at :119); env.txt (no AMD GPU: pciconf shows only virtio-gpu 1af4:1234); fix.diff (2 NULL guards)", "kernel_refs": [ "sys/dev/drm/amd/amdgpu/amdgpu_irq.c:359", "sys/dev/drm/amd/amdgpu/amdgpu_irq.c:436", "sys/dev/drm/amd/amdgpu/amdgpu_irq.c:467", "sys/dev/drm/amd/amdgpu/amdgpu_irq.c:134", "sys/dev/drm/amd/amdgpu/amdgpu_irq.c:488", "sys/dev/drm/amd/amdgpu/amdgpu_irq.c:520", "sys/dev/drm/amd/amdgpu/amdgpu_irq.c:550", "sys/dev/drm/amd/amdgpu/amdgpu_irq.c:237", "sys/dev/drm/amd/amdgpu/dce_virtual.c:375", "sys/dev/drm/amd/amdgpu/dce_virtual.c:757", "sys/dev/drm/amd/amdgpu/sdma_v4_0.c:1748", "sys/dev/drm/amd/amdgpu/amdgpu_device.c:3287", "sys/dev/drm/include/linux/spinlock.h:75", "sys/dev/drm/include/linux/irqflags.h:34" ], "poc_changes": "n/a (no runtime PoC attempted; no AMD GPU on guest per DF-4519/DF-2201 hardware-gated protocol)", "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": 2400, "guest_dirty": 1, "build_cmd": "cd /usr/src && patch -p1 < /tmp/df4713_fix.diff && cd /usr/src/sys/dev/drm/amd/amdgpu && make obj && make", "run_cmd": "n/a (no AMD GPU on guest; amdgpu never probes)", "code_hash": null, "notes": "Verified across all 61 amdgpu_irq_add_id call sites: every num_types>0 source defines .set (illegal_inst sources lack .set but carry num_types==0), so the .set hole is not reachable with the current registry; the .process hole has exactly one in-tree NULL provider (dce_virtual crtc_irq). Negative results: fini double-registration safe (all double-registered srcs are static, data==NULL, enabled_types kfree(NULL) on 2nd pass); dispatch-vs-fini UAF closed by drm_irq_uninstall->free_irq->bus_teardown_intr synchronization before the kfree loop; add_id bounds/dup checks correct; get/put converge via amdgpu_irq_enabled re-read under lock; virk empty-then dead code.", "recommended_fix": "NULL-guard the two optional-callback calls: skip with DRM_DEBUG when funcs->process is NULL in amdgpu_irq_dispatch; return -EINVAL (after unlocking) when funcs->set is NULL in amdgpu_irq_update - matching the guards already used by amdgpu_irq_disable_all/amdgpu_irq_get/amdgpu_irq_put.", "fix_status": "fixed", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "build-only validation (runtime hardware-gated): fix.diff applied to guest /usr/src; full amdgpu KLD module build (make -C /usr/src/sys/dev/drm/amd/amdgpu) completed MOD_BUILD_RC=0 with -Werror; patched amdgpu_irq.c compiled at build.log:119 and amdgpu.ko linked. Baseline/patched runtime not observable without an AMD GPU.", "fix_evidence": "findings/poc/DF-4713/build.log (full untrimmed module build; decisive lines: 119 patched amdgpu_irq.c -Werror compile, 354 MOD_BUILD_RC=0)" } |