# DF-4975 VERDICT — VERIFIED-BY-TRACE, NOT EXECUTED (hardware absent)

**status: untested | reproduced: 0 | impact: none (on this guest) | code-path confidence: certain / manifestation: likely**

## Why this is a real defect (line-by-line)

1. **Enabling before init.** `xgpu_ai_mailbox_get_irq()`:
   - mxgpu_ai.c:351 `amdgpu_irq_get(adev, &adev->virt.rcv_irq, 0)` — first
     enable of the source (refcount 0→1) calls `amdgpu_irq_update()`
     (amdgpu_irq.c:511-525) which invokes the `.set` callback
     `xgpu_ai_set_mailbox_rcv_irq` (mxgpu_ai.c:273-285) → writes
     VALID_INT_EN=1 to `mmBIF_BX_PF0_MAILBOX_INT_CNTL` (mxgpu_ai.c:280-282).
     From this instruction onward the device can raise the mailbox RCV irq.
   - mxgpu_ai.c:360 `INIT_WORK(&adev->virt.flr_work, xgpu_ai_mailbox_flr_work)`
     — the work is only now given a `func`. Between 351 and 360 it is a
     zeroed blob (`adev` is kzalloc'd, amdgpu_kms.c:180-183; no other
     initializer exists — `INIT_WORK` for `flr_work` appears exactly once in
     the tree, at mxgpu_ai.c:360).

2. **The ISR path is live in that window.** `xgpu_ai_mailbox_rcv_irq`
   (mxgpu_ai.c:287-310): peeks RCV_DW0 (line 291); for
   `IDH_FLR_NOTIFICATION` (line 294) checks `amdgpu_sriov_runtime(adev)`
   (line 295) then `schedule_work(&adev->virt.flr_work)` (line 296).
   - RUNTIME bit proven set before late_init:
     `amdgpu_device_init()` ends with
     `amdgpu_virt_release_full_gpu(adev, true)` at amdgpu_device.c:1696,
     which sets `AMDGPU_SRIOV_CAPS_RUNTIME` (amdgpu_virt.c:282).
     `amdgpu_device_ip_late_init()` (amdgpu_device.c:2700) →
     `soc15_common_late_init` (soc15.c:800-804) → `get_irq()` runs strictly
     after. So line 295's gate is open.
   - In this port `.process` handlers run in hard-IRQ context (same basis
     as DF-4756's "hard-IRQ .process handler"); `schedule_work` from
     hardirq is supported and intended.

3. **What a zeroed work does under the DFly shim.**
   `struct work_struct` (sys/dev/drm/include/linux/workqueue.h:47-56):
   `ws_entries` (STAILQ), `func`, `worker`, `on_queue`, `running`,
   `canceled`. Zeroed ⇒ `func == NULL`, `on_queue == false`.
   `queue_work()` (sys/dev/drm/linux_workqueue.c:120-140): sees
   `on_queue == false` → `STAILQ_INSERT_TAIL` (overwrites the NULL link
   pointers — no immediate list corruption) → marks on_queue.
   Worker `process_all_work()` (linux_workqueue.c:66-100): dequeues, sets
   `running = true`, drops worker_lock, then line 89 `work->func(work)` →
   **indirect call through NULL** ⇒ kernel panic. This is exactly the
   mechanism DF-4755 documented for the VI twin.

4. **Host control of the trigger.** The PF writes RCV_DW0 and sets
   RCV_MSG_VALID; the VF cannot block that. The window is short
   (two register round-trips) but re-opens on every resume
   (`amdgpu_device_resume` re-runs `amdgpu_device_ip_late_init`,
   amdgpu_device.c:2936). A host that performs an FLR around VM resume has
   a realistic shot at the window; an unlucky benign host can hit it too.
   Consequence: guest kernel panic (availability only; no control over the
   called pointer — it is deterministically NULL).

## Why not executed on the guest (honest boundary)

The audit QEMU guest (`DragonFly dfbsd 6.5-DEVELOPMENT #0 ... X86_64_GENERIC`)
has:
- no AMD GPU at all — the only display device is QEMU std VGA
  (`vgapci0@pci0:0:2.0 ... chip=0x1111234`, see env.txt);
- no SR-IOV virtual function (it is not an SR-IOV guest);
- no drm/amdgpu compiled into the running kernel
  (`sysctl kern.conftxt` matches zero `drm|ath` devices).

The code path additionally requires a host/PF to time an FLR notification
into the probe window. Running the guest cannot produce this by any local
action; classification is therefore **untested on this hardware** rather
than not_reproduced. The defect itself is proven by the static trace above
(every hop cited path:line).

## Exploit chain

None — the called pointer is NULL by construction (kzalloc), so the
outcome is a deterministic panic, not controlled execution. Impact ceiling:
host-timed guest DoS at probe/resume. Rated **Low**, mirroring DF-4755.

## Fix validation

fix_status: **not_testable** — fix.diff (INIT_WORK moved above both
`amdgpu_irq_get` calls) is authored but cannot be built+exercised on this
guest for the same hardware-absence reason. The change removes the window
by construction: the work is fully initialized before the interrupt source
can deliver anything.

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
