# DF-4439 — drm_atomic_state holds no drm_device reference (missing backport of upstream 4e076c73e4f6)

`sys/dev/drm/drm_atomic.c` (DragonFly DRM port, Linux v4.19-faithful)

## What

`drm_atomic_state_init()` (sys/dev/drm/drm_atomic.c:77) never takes a
reference on the `drm_device`, and `__drm_atomic_state_free()`
(sys/dev/drm/drm_atomic.c:251) never drops one — while a **nonblocking**
atomic commit (`drm_atomic_nonblocking_commit`, sys/dev/drm/drm_atomic.c:1069,
called from the `DRM_MODE_ATOMIC` ioctl at sys/dev/drm/drm_atomic_uapi.c:1368)
queues `state->commit_work` onto the **system-wide** `system_unbound_wq`
(sys/dev/drm/drm_atomic_helper.c:1701,1745).  The ioctl then returns and the
`drm_atomic_state` (and its `state->dev` pointer) is only released from the
asynchronous commit tail.

Upstream fixed exactly this in Linux commit **4e076c73e4f6** ("drm/atomic: Fix
potential use-after-free in nonblocking commits", Cc: stable, merged 2023):
grab `drm_dev_get()` in `drm_atomic_state_init()` and `drm_dev_put()` in
`__drm_atomic_state_free()`.  That fix is absent here.

## Consequence

If the `drm_device` is freed while a nonblocking commit is still in flight —
driver unload (`kldunload drm/radeon/amdgpu/i915kms`, all built as modules in
`/boot/kernel`) or any `drm_dev_unplug()` caller — the commit tail and the
final `drm_atomic_state_put()` run `drm_atomic_state_clear(state)` and
`__drm_atomic_state_free()` against freed memory:

* `drm_atomic_state_default_clear()` reads `state->dev->mode_config`
  (drm_atomic.c:144) and walks `config->num_crtc` / `num_total_plane`,
* `__drm_atomic_state_free()` calls `config->funcs->atomic_state_free`
  (drm_atomic.c:261) — an indirect call through freed memory.

Unprivileged half: any DRM master (the desktop user) can keep nonblocking
commits queued.  Privileged half: the unload.  Upstream shipped the fix to
stable because the drm_dev_unplugged() checks are by design racy against
outstanding ioctls/work.

## Verification on this audit guest

`probe_drm.c` was built and run on the DragonFly 6.5-DEVELOPMENT guest
(cc 8.3): **no DRM device node exists** (`/dev/drm*`, `/dev/dri/*` absent);
the DRM core module loads but no KMS driver in the port (i915/radeon/amdgpu)
attaches to the QEMU std VGA (0x1234:0x1111).  The race therefore cannot be
driven on this guest → verdict **inconclusive** (runtime), while the code
defect itself is **certain** (verified by function-for-function diff against
upstream v4.19 plus the stable-cc'd fix commit).

## Fix

`fix.diff` is the direct backport of upstream 4e076c73e4f6 against
`sys/dev/drm/drm_atomic.c`.  Fix validation (build patched kernel + rerun) is
`not_testable` for the same reason (baseline cannot run on this guest).
