⬢ DragonFlyBSD Kernel Audit
DF-4143 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4143",
  "status": "reproduced",
  "verdict": "REPRODUCED via the verbatim-code rig: trinity_dpm_enable/trinity_dpm_disable/trinity_dpm_pre_set_power_state and every layout-relevant struct were machine-extracted byte-identical from sys/ (68 blocks re-verified identical ON THE GUEST against /usr/src/sys, the tree its running kernel was built from) and driven with crafted Trinity DPM VBIOS images. Baseline production code: a table with no BOOT-classified state parses successfully (init rc=0, num_ps=2) leaving boot_ps NULL; the verbatim trinity_dpm_enable then faults reading NULL->ps_priv at exactly address 0x28 (40 = offsetof(struct radeon_ps, ps_priv), printed from the verbatim struct) at trinity_dpm.c:1129 -> trinity_update_current_ps:1075 -> trinity_get_ps:355. requested_ps NULL (the radeon_pm.c:1449 value) faults pre_set_power_state at address 0x0 (:1240). A parse aborted by a NULL power_state[i].clock_info word (:1777-1778, the DF-4146 chain) with the error swallowed per radeon_pm.c:1448-1453 faults enable at 0x28 as well. A good-table regression passes end-to-end (init/enable/disable/pre_set/get_sclk/fini). In kernel context each fault is a page fault -> panic at GPU attach or first suspend (reboot-loop DoS on a crafted-VBIOS Trinity/Richland APU; root-writable pp_table after DPM reinit). Gating: no AMD GPU on the audit guest (Boches 0x1234:1111 only, env.txt), so the guest kernel never executes the path; reproduction is in the verbatim rig per the established evidence class for crafted-firmware parsers (DF-4165/DF-4247/DF-4388/DF-4396). fix.diff (NULL guards at all three dispatch entries) A/B-validated in the same rig on identical images: all three modes return -EINVAL cleanly, good table unchanged.",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "exploit_chain": "Crafted/corrupted VBIOS (flashed ROM, vfio-pci romfile=, malicious device) on a Trinity/Richland APU with no BOOT-classified pplib state (or any parse failure whose error radeon_pm.c:1448 discards) -> radeon_pm_init_dpm:1448 swallows trinity_dpm_init error -> :1449 current_ps=requested_ps=boot_ps=NULL -> :1453 radeon_dpm_enable -> trinity_dpm_enable:1129 trinity_update_current_ps(rdev, NULL) -> trinity_get_ps reads rps->ps_priv at NULL+40 -> kernel page fault -> panic at drm attach and at every suspend (radeon_pm.c:1257-1260 radeon_dpm_disable -> :1177 same deref). No unprivileged-userland trigger: the attacker data is the GPU ROM, not syscalls.",
  "evidence": "run.log (all 14 modes, baseline vs fixed; modes 4143-enable/4143-presel/4143-initfail: FAULT addr=0x28 / 0x0 / 0x28 with the NULL-member-offset notes), run.2.log (stability repeat), build.log (68x identical to production against guest /usr/src/sys + DF-4143 fix lines == fix.diff additions (8 lines) + zero-error build of both binaries), rig/ (sources: trinity_slice_verbatim.c carries the production functions between VERBATIM markers; trinity_rig.c drives the crafted images with guard/canary pages), VERDICT.md, env.txt (hardware gating)",
  "kernel_refs": [
    "sys/dev/drm/radeon/trinity_dpm.c:1129",
    "sys/dev/drm/radeon/trinity_dpm.c:1177",
    "sys/dev/drm/radeon/trinity_dpm.c:1240",
    "sys/dev/drm/radeon/trinity_dpm.c:1704",
    "sys/dev/drm/radeon/trinity_dpm.c:1075",
    "sys/dev/drm/radeon/trinity_dpm.c:355",
    "sys/dev/drm/radeon/radeon_pm.c:1448",
    "sys/dev/drm/radeon/radeon_pm.c:1453",
    "sys/dev/drm/radeon/radeon_pm.c:1705"
  ],
  "poc_changes": "Seed pack had no runnable PoC (status untested, hardware-gated). Built the verbatim rig from scratch: gen_rig.sh machine-extracts the production slice; check_verbatim.sh proves block identity (guest /usr/src/sys) and that the APPLY_DF4143_FIX lines are exactly fix.diffs additions; the harness crafts full AtomBIOS images (master data table indirection, PowerPlayInfo table, state/clock/non-clock arrays, IntegratedSystemInfo v1_7 with crev=7) so the verbatim atom_parse_data_header -> trinity_dpm_init -> enable/disable/pre_set chain executes; guarded page allocator + SIGSEGV classifier names NULL-deref/UAF/OOB classes with exact offsets.",
  "attempts": 3,
  "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": 150,
  "guest_dirty": 0,
  "build_cmd": "cd rig && sh ./build.sh /usr/src DF-4143",
  "run_cmd": "cd rig && sh ./run.sh",
  "code_hash": "trinity_rig.c a68eb1438bc82fb79063491af6293aeddf208ec2cf4f46f0c6040a1aed69e1a3; trinity_slice_verbatim.c 6afb17099769a0c4c9cd500356a757a12cf22d8e9bd67a710b452236019ba7c6",
  "notes": "Fault addresses match struct offsets computed from the verbatim structs (ps_priv@40 in the 48-byte struct radeon_ps). radeon_pm.c:1448s error swallow (out of file scope for fix.diff) is the systemic enabler; the in-file guards make all three dispatch entries safe regardless. Guest left up and clean: pack working dir /root/df-trinity removed after artifact retrieval.",
  "recommended_fix": "NULL-guard rdev->pm.dpm.boot_ps at the head of trinity_dpm_enable/trinity_dpm_disable and rdev->pm.dpm.requested_ps in trinity_dpm_pre_set_power_state (fix.diff, A/B validated); long-term: honor trinity_dpm_inits return in radeon_pm.c:1448.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "A/B validated in the verbatim rig: identical crafted images, same slice, only the fix.diff lines added under -DAPPLY_DF4143_FIX. Baseline: NULL-deref faults at 0x28/0x0 in all three modes. Fixed: every mode returns -EINVAL cleanly (guards fire before any deref), good-table regression unchanged. Kernel-rebuild validation not performed (fix site executes only on AMD Trinity ASICs, absent from this guest); per the verbatim-rig protocol the fixed slice was validated in the same rig. fix.diff authored against the pristine read-only sys/ tree, never applied there.",
  "fix_evidence": "run.log FIXED sections (RESULT: OK (fixed) ... rejected cleanly, rc=-22); build.log (DF-4143 fix lines == fix.diff additions (8 lines)); fix.diff"
}