# DF-4625 VERDICT — REPRODUCED (in-kernel KLD, verbatim shim + real primitives)

**Status:** reproduced / impact: dos (post-cancel execution → mid-suspend
probe or teardown UAF) / confidence: certain.

## Root cause (traced line by line)

* drm_probe_helper.c:653-654 — `output_poll_execute()` unconditionally
  re-arms itself (`repoll` is true whenever any polled connector exists).
* drm_probe_helper.c:695-700 / :735-739 — `drm_kms_helper_poll_disable()`/
  `poll_fini()` delegate the kill to `cancel_delayed_work_sync()`.
* linux_workqueue.c:415-424 — the shim cancels the callout **before**
  waiting out the running callback; when the callback then re-arms
  (callout_reset arms a fresh timer; DFBSD callouts only refuse resets
  while a CANCEL request is still queued — kern_timeout.c:293 checks
  `CALLOUT_CANCEL` *at wheel-processing time*, and `_callout_cancel_or_stop`
  on an idle timer consumes/clears the request immediately at
  kern_timeout.c:1032), nothing re-cancels afterwards.
* linux_workqueue.c:348-385 — `_cancel_work()` breaks as soon as
  `on_queue == 0 && running == 0`; a pending timer is not part of its
  idle predicate.
* linux_workqueue.c:135 — when the surviving timer fires,
  `queue_work()` clears `work->canceled`, so the full callback re-executes.

Net effect: `cancel_delayed_work_sync()` returns while the work is
guaranteed to run once more (up to `DRM_OUTPUT_POLL_PERIOD` = 10 s later,
drm_probe_helper.c:206). Consumers:

* suspend: amdgpu_device.c:985/:2813, radeon_device.c:1233/:1620,
  i915_drv.c:1983 → full connector detect (i2c/aux reads + MMIO) against
  a suspending/suspended GPU → hang/panic.
* teardown: i915_drv.c:1663, amdgpu dce_v8/10/11/virtual fini,
  radeon_display.c:1652, drm_modeset_helper.c:185 → the work executes on
  a drm_device being freed → UAF (`dev->mode_config` reads, connector
  walks via kref-protected iters on freed memory).

## How it was proven (guest, DragonFly 6.5-DEVELOPMENT, real kernel)

A KLD (`df4625.c`) that `sed`-extracts the shim functions **verbatim**
from `/usr/src/sys/dev/drm/linux_workqueue.c` (ranges in build.sh) and
compiles them against the real `lockmgr`/`lksleep`/`callout_reset`/
`callout_cancel`/lwkt-thread kernel primitives. The scenario emulates the
poll worker: a callback that re-arms itself with
`schedule_delayed_work()` while a canceller thread runs
`cancel_delayed_work_sync()` mid-callback — the exact interleaving a
suspend or `poll_fini()` hits when it races the 10 s poll cycle (probe
cycles run for hundreds of ms, so the overlap is a per-event probability
that compounds over suspend/resume cycles).

Decisive dmesg (run.log):

    BASELINE:
      canceller: cancel_delayed_work_sync() RETURN (timer pending=1 on_queue=0 running=0)
      EXEC #2 entered
      DF-4625 REPRODUCED: work executed AFTER cancel_delayed_work_sync() returned
    FIXED (fix.diff):
      canceller: cancel_delayed_work_sync() RETURN (timer pending=0 on_queue=0 running=0)
      FIX VALIDATED: no execution after cancel_delayed_work_sync() returned

`timer pending=1` at cancel-return is the structural miss observed
directly in-kernel, not inferred. (The four "interface/module already
present" lines in run.log are earlier failed-load attempts of the fixed
module before its module id was renamed — kept for honesty.)

## Why dos-grade and not higher

The post-cancel execution runs fixed kernel code (the poll worker) on a
freed/suspended object; there is no attacker-controlled write primitive.
Realistic ceiling: repeatable suspend/resume or driver-teardown crash /
hang (needs a drm-driven GPU and timing overlap). The guest's
X86_64_GENERIC has no drm compiled in (`optional drm`), so the real poll
path could not be exercised on it — hence the KLD reproduces the exact
code and primitives rather than the driver itself.

## Fix validation

`fix.diff` replaces `cancel_delayed_work_sync()`'s one-shot sequence with
a converging loop (`_cancel_work` until `callout_cancel()` returns 0 and
the work is idle). Convergence argument: any re-arm happens before the
callback returns (i.e., before `running == false` is observed), so the
loop's `callout_cancel` always observes the last-armed timer; a timer
firing mid-loop is covered by `callout_cancel`'s synchronous wait on
`CALLOUT_INPROG` (kern_timeout.c). Validated on the same kernel: fixed
module returns with `pending=0` and no post-cancel execution.

Filed against drm_probe_helper.c (the victim whose
`drm_kms_helper_poll_disable`/`poll_fini` contract is violated); the
causal patch lands in linux_workqueue.c — a file whose pass-1 findings
(DF-1976..1980) did not cover this self-rearm cancel miss.

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