# DF-4525 evidence pack

**Finding:** amdgpu_dpm.c error-path double/triple free of all
`pm.dpm.dyn_state` power-table pointers (`amdgpu_free_extended_power_table`
frees without NULLing; internal parse error paths + ci/si/kv `*_dpm_fini`
teardowns free again).

## Reproduce

```sh
# guest: DragonFly 6.5-DEVELOPMENT QEMU snapshot (dfbsd-qemu/vm.sh up)
./build.sh        # scp + build df4525demo.ko against guest /usr/src
./run.sh          # baseline: stock amdgpu.ko  ->  kernel PANIC (serial console)
./fix_validate.sh # apply fix.diff to guest /usr/src, rebuild amdgpu.ko, rerun -> clean
```

## Expected

* **Baseline:** `panic: memory chunk 0xfffff8008976ba00 is already free!`
  with `amdgpu_free_extended_power_table()` in the trace; `vm.sh status` ⇒
  down. (run.log, panic.txt)
* **Patched:** `after 1st free: vddc=0 vddci=0`, second call is
  `kfree(NULL)`, 4 distinct re-allocs, `MODULES LOADED, NO PANIC`, guest
  stays up. (fix_run.log)

## Files

| file | what |
|---|---|
| `df4525demo.c` | KLD performing the driver's exact double-free call sequence against the real shipped `amdgpu_free_extended_power_table()` |
| `Makefile` | module build (include set mirrors `sys/dev/drm/amd/amdgpu/Makefile` so struct layouts match the shipped .ko) |
| `build.sh` / `run.sh` / `fix_validate.sh` | exact commands |
| `run.log`, `panic.txt` | baseline panic (serial console capture) |
| `demo_build.log`, `fix_build.log` | untrimmed module + patched-amdgpu.ko build logs |
| `fix_run.log` | patched-module rerun (no panic) |
| `fix.diff` | NULL-after-free for all 13 dyn_state pointers (git-apply-able) |
| `VERDICT.md` | full narrative |
| `manifest.json` / `verdict.json` | machine-readable |
