⬢ DragonFlyBSD Kernel Audit
DF-3666 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3666",
  "status": "inconclusive",
  "reproduced": 0,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Arithmetic proven, hardware-bound containment documented. sumo_rlc_init() allocates the RLC save/restore buffer object as dws*4 = 81*4 = 324 bytes (evergreen.c:4155) but the ON/LN/TN packing loop (evergreen.c:4197-4206) writes the 2-regs-into-3-dwords format plus an end marker, touching dword indices up to ceil(81/2)*3 = 123 -> 496 bytes needed: a 43-dword / 172-byte write past the declared BO size. The PoC replays the exact loop and prints the overrun (deterministic). Impact today is none: TTM backs the BO with whole pages (num_pages rounds 324 -> 1 page) and 496 < 4096, so the overrun lands in slack of the objects own backing page; values written are compile-time constants. Filed Low/hardening: any sub-page-granular VRAM allocator or reuse of the shared packing loop (ni.c:2204 passes the ARUBA tn_rlc_save_restore_register_list through the same code - cross-file lead) turns it into real neighbor-object corruption. Kernel-path execution requires PALM/SUMO/SUMO2 hardware absent from the virtio-only guest, hence inconclusive (hardware-absent convention), not not_testable.",
  "exploit_chain": "",
  "evidence": "run.log: OOB write past BO size: 43 dwords = 172 bytes and RESULT: BUG REPRODUCED - writes need 496 bytes but the BO is 324 bytes; df3666.c replays evergreen.c:4197-4206 verbatim with dws=81 (ARRAY_SIZE of sumo_rlc_save_restore_register_list, evergreen.c:123-206); VERDICT.md containment analysis (TTM page rounding); fix.diff sizes the BO to ((dws+1)/2)*3+1 dwords",
  "kernel_refs": [
    "sys/dev/drm/radeon/evergreen.c:4155",
    "sys/dev/drm/radeon/evergreen.c:4197",
    "sys/dev/drm/radeon/evergreen.c:4205",
    "sys/dev/drm/radeon/evergreen.c:5017",
    "sys/dev/drm/radeon/evergreen.c:123",
    "sys/dev/drm/radeon/ni.c:2204"
  ],
  "poc_changes": "Seed was a sketch; written from scratch as a deterministic index-math replay with a TTM page-rounding model to state the containment honestly (no heuristic byte-pattern guessing left in the final version).",
  "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": 120,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -Wall -o df3666 df3666.c",
  "run_cmd": "./df3666",
  "code_hash": "597b3dbd90e19f719c909b070413e441f3d534fb05aafa8f99b2c7f88574012f",
  "notes": "Guest lacks any radeon IGP; the write executes during evergreen_startup() on RADEON_IS_IGP parts only. Upstream Linux fixed the same undersizing with the equivalent allocation-size expression. Cross-file lead: ARUBA path via ni.c:2204 uses the same packing loop with tn_rlc_save_restore_register_list.",
  "recommended_fix": "Allocate the save/restore BO for the packed format: sr_dws = ((dws + 1) / 2) * 3 + 1 dwords for pre-TAHITI (evergreen.c:4155)",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff sizes the allocation to 124 dwords (496 bytes) >= highest written index 123 for dws=81 - validated arithmetically by the same PoC model; cannot be kernel-tested without SUMO-class hardware, so fix_status=not_testable.",
  "fix_evidence": "fix.diff; VERDICT.md Fix and Fix validation sections"
}