# VERDICT — DF-4439

**Status: inconclusive (runtime) / defect certain (source)**
**Impact ceiling: use-after-free → kernel memory corruption (root-assisted race)**

## Was it reproduced?

No — and the reason is environmental, not evidentiary.  The audit guest
(DragonFly 6.5-DEVELOPMENT, `X86_64_GENERIC`, QEMU std VGA 0x1234:0x1111)
has **no DRM device**: `probe_drm.c` (pack) enumerates `/dev/drm*` and
`/dev/dri/*` — all absent (`run.log`).  The port's KMS drivers (i915,
radeon, amdgpu) exist as loadable modules (`/boot/kernel/radeon.ko`,
`amdgpu.ko`, …) but none binds the emulated VGA, so the
`DRM_IOCTL_MODE_ATOMIC` entry path cannot even be opened here.  `drm.ko`
loads but creates no device without a driver attach.

## Why the defect is certain anyway

1. `sys/dev/drm/drm_atomic.c` is a function-for-function copy of Linux v4.19
   `drivers/gpu/drm/drm_atomic.c` (verified by extraction diff — only two
   cosmetic deviations: `%jx` vs `%llx` at drm_atomic.c:554 and `M_DRM` in
   the krealloc at drm_atomic.c:726).
2. Nonblocking commits run past the ioctl lifetime:
   * `drm_mode_atomic` ioctl → `drm_atomic_nonblocking_commit`
     (sys/dev/drm/drm_atomic_uapi.c:1368 → sys/dev/drm/drm_atomic.c:1080),
   * → `drm_atomic_helper_commit()` nonblock path:
     `INIT_WORK(&state->commit_work, commit_work)` and
     `queue_work(system_unbound_wq, &state->commit_work)`
     (sys/dev/drm/drm_atomic_helper.c:1701,1745),
   * the last `drm_atomic_state_put()` for that state happens in the commit
     tail / completion — after the ioctl has returned.
3. `drm_atomic_state_init()` (sys/dev/drm/drm_atomic.c:77-104) sets
   `state->dev = dev` with **no `drm_dev_get()`**; `__drm_atomic_state_free()`
   (sys/dev/drm/drm_atomic.c:251-266) dereferences `state->dev->mode_config`
   and calls `config->funcs->atomic_state_free` with **no `drm_dev_put()`**.
   The only references keeping `drm_device` alive are the open drm file
   (`drm_file`) and minors — exactly the situation upstream describes in
   4e076c73e4f6: "the atomic modeset ioctl can be run in a nonblocking
   fashion, and in that case it cannot rely on the implied drm_device
   reference provided by the ioctl calling context. This can result in a
   use-after-free if a nonblocking atomic commit is carefully raced against
   a driver unload."
4. `drm_dev_get`/`drm_dev_put` exist in the port
   (sys/dev/drm/drm_drv.c:761, :354; release frees via kref at :737), and
   the port carries the `drm_dev_unplug`/`drm_dev_enter` API
   (sys/dev/drm/drm_drv.c:360-400) — the backport applies cleanly.

## The race (on real hardware)

* Attacker A (unprivileged, DRM master — the logged-in desktop user): issue
  `DRM_IOCTL_MODE_ATOMIC` with `DRM_MODE_ATOMIC_NONBLOCK` in a tight loop,
  keeping commit work queued on `system_unbound_wq`.
* Attacker B (root): `kldunload radeon` (or amdgpu/i915kms, all modules) at
  the same moment — or any future `drm_dev_unplug()` caller.
* If the `drm_device` kref hits zero between the ioctl returning and the
  commit tail's `drm_atomic_state_put()`, `__drm_atomic_state_free()` and
  `drm_atomic_state_default_clear()` operate on freed memory, including an
  indirect call `config->funcs->atomic_state_free(state)` — classic UAF
  primitive (attacker-influenceable heap contents via slab reuse of the
  `drm_device`).

Both halves are needed, hence severity Medium rather than High (the free side
requires privilege; DF default GENERIC does not auto-load these drivers — but
every real GPU laptop/userland stack loads them).

## Fix validation

`fix.diff` (this pack) is the exact backport of upstream 4e076c73e4f6.
Baseline-vs-patched kernel testing is **not_testable** on this guest: the
baseline itself cannot run (no DRM device).  The patch is trivially
reviewable against the upstream commit.

## Guest state

Guest left clean (probe binary under /tmp, source under /root/poc; no kernel
changes, no panic, no reset needed).

## 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.
