# DF-4919 — cancel_work_sync()/flush_work() read per-work flags without the guarding lock: premature "idle" return while the work is about to execute → UAF-class contract violation

`sys/dev/drm/linux_workqueue.c` — `process_all_work()` dequeues a work and
only afterwards marks it running, with the whole transition under
`worker_lock`:

```c
74:   work->on_queue = false;        /* dequeued            */
87:   work->running = true;          /* about to run func() */
```

`queue_work()` publishes the insert under the target worker's lock
(:134-146), but `_cancel_work()` and `flush_work()` read `on_queue` /
`running` **without any lock**:

```c
331:  while (work->on_queue || work->running)   /* flush_work   */
349:  if (work->on_queue) { ... }               /* _cancel_work */
364:  if (work->running == false) break;        /* RETURN       */
```

A caller whose load pair straddles (a) the worker's dequeue→start
transition or (b) a concurrent `queue_work()` insert publication observes
`on_queue==false && running==false` and returns — **while the work
function is about to execute** — directly violating the contract spelled
out above `cancel_work_sync()` (lines 390-394): *"callers may free
associated data structures after this call."*  A caller that frees (kfree
of the container, or return of the stack frame holding an
`INIT_WORK_ONSTACK` work, e.g. drm_framebuffer.c:475-481 `drm_mode_rmfb`,
an unprivileged DRM ioctl path) leaves `process_all_work()` about to call
`work->func(work)` through freed / stack-reused memory: **arbitrary-call
use-after-free**.  In the race case `cancel_work_sync()` also returns
FALSE ("work wasn't pending") for a work that was queued and executes —
the demonstrable lie.

Linux resolves exactly these races with the `WORK_STRUCT_PENDING` atomic
claim (queue vs cancel vs flush are coherent); the shim has no such
protocol, and the flags are guarded by *different* (or no) locks.

## Build (guest, root)

```sh
kldload drm                # workqueue shim lives in drm.ko
cd /tmp/df4919 && make
```

## Run

```sh
kldload /tmp/df4919/df4919.ko
sysctl hw.df4919_test=1    # cancel_work_sync race; safe stop+report (~90s)
# crash proof (guest panics):
sysctl hw.df4919_test=2
sysctl hw.df4919_status    # counters
```

## Expected

Unpatched (baseline): a `*** POSTHUMOUS EXECUTION AFTER SYNC-CANCEL/FLUSH
RETURN — CONFIRMED ***` line (work function ran with the alive-flag the
canceller cleared after `cancel_work_sync()` returned), or — test=2 —
`panic: DF-4919: work executed AFTER cancel_work_sync() returned` with
trace `wk_func() <- wq_worker_thread()` (panic.txt).

Patched (claim protocol + flags spinlock): no classifier-confirmed hit in
multi-million-cancel runs; guest healthy through 90 s of hammering.
