{
  "finding_id": "DF-4580",
  "status": "not_reproduced",
  "reproduced": 0,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Full trigger (DRM_IOCTL_RADEON_CS with crafted num_chunks) cannot run on the audit guest: it has no AMD/ATI GPU and no /dev/dri, so radeon_cs_ioctl is unreachable there. The code path is certain by inspection: radeon_cs_parser_init sizes wired GFP_KERNEL allocations from the uncapped u32 num_chunks (8n bytes at radeon_cs.c:287, 24n at :298, 4*length_dw at :346), and DragonFly maps GFP_KERNEL to M_WAITOK WITHOUT M_NULLOK (gfp.h:40), so allocation failure is panic(M_DRM: malloc limit exceeded) at kern_slaballoc.c:877 (num_chunks ~40-50M pushes the first 320-400MB alloc over the physmem/10 type limit, next kcalloc panics) or an eternal unkillable vm_wait() loop (kern_slaballoc.c:1780-1806) for num_chunks=0xFFFFFFFF (32GB request > physmem). The sink mechanism was independently REPRODUCED on the guest with a kld performing the identical M_WAITOK|M_ZERO no-M_NULLOK allocation pattern: panic df4580: malloc limit exceeded at alloc #13 (416MB cumulative vs 389MB limit), backtrace _kmalloc -> df4580_modevent (panic.txt, run.log). Additionally the Linux-shaped NULL-return path would NULL-deref parser->chunks[i] in radeon_cs_parser_fini (radeon_cs.c:447-448) with chunks==NULL/nchunks>0; on DF as compiled this is masked by the allocation panic (kmem_slab_alloc never returns NULL without M_NULLOK) but becomes live if allocator flags are fixed without also fixing fini.",
  "exploit_chain": "",
  "evidence": "panic.txt + run.log: df4580: alloc #13 (type usage ~416 MB) then panic: df4580: malloc limit exceeded with _kmalloc backtrace = the exact sink radeon_cs.c:287/298 rides; VERDICT.md section Code trace of the trigger for the ioctl-side chain; build.log for the kld build; fix.diff applies cleanly (git apply --check).",
  "kernel_refs": [
    "sys/dev/drm/radeon/radeon_cs.c:287",
    "sys/dev/drm/radeon/radeon_cs.c:298",
    "sys/dev/drm/radeon/radeon_cs.c:346",
    "sys/dev/drm/radeon/radeon_cs.c:447",
    "sys/dev/drm/include/linux/gfp.h:40",
    "sys/kern/kern_slaballoc.c:877",
    "sys/kern/kern_slaballoc.c:1724",
    "sys/kern/kern_slaballoc.c:1780"
  ],
  "poc_changes": "No PoC seed existed; authored from scratch. kld module reproduces the DF GFP_KERNEL allocation-failure sink (M_WAITOK|M_ZERO, no M_NULLOK, own malloc type with the standard physmem/10 limit) rather than the ioctl path, because the guest lacks AMD GPU hardware. One build fix: DECLARE_MODULE argument (moduledata_t, not handler).",
  "attempts": 2,
  "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": 210,
  "guest_dirty": 0,
  "build_cmd": "cd /root/df4580 && make",
  "run_cmd": "kldload /root/df4580/df4580.ko   (expect: panic df4580: malloc limit exceeded)",
  "code_hash": "cb6de8594a0f5023455e8204653c4d0afb9a22abc0ea785613d1db248bc96fa1",
  "notes": "Guest has no AMD GPU (pciconfig -l has no 1002: device; /dev/dri absent) -> radeon_cs_ioctl itself not testable on this guest; sink mechanism proven instead. Guest panicked by design during verification and was reset to the with-src snapshot afterwards (module no longer loaded). Fix validation not runnable for the same hardware reason.",
  "recommended_fix": "Cap num_chunks (<=64) and per-chunk length_dw (<=1M dwords) in radeon_cs_parser_init before allocating, and NULL-guard the parser->chunks loop in radeon_cs_parser_fini.",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff authored and git-apply-check clean, but baseline/patched behavior cannot be exercised on this guest (no radeon hardware); the mechanism kld is unaffected by the radeon-side fix.",
  "fix_evidence": "findings/poc/DF-4580/fix.diff (3 hunks: num_chunks cap, length_dw cap, fini NULL-guard); git apply --check passes."
}