# DF-2175: hrtimer_start_range_ns corrupts per-CPU systimer queue

## Verdict: NOT REPRODUCED (HW-gated) — source-confirmed real bug

## Reachability
**NOT reachable on this QEMU guest.** `hrtimer_start_range_ns()` is in
`sys/dev/drm/linux_hrtimer.c`, part of `drm.ko`. Used by DRM GPU drivers. Without GPU
hardware, no hrtimers are started via this path.

## Mechanism (source-confirmed)
`hrtimer_start_range_ns()` at `linux_hrtimer.c:87-119`:
```c
void hrtimer_start_range_ns(struct hrtimer *timer, ...) {
    ...
    lwkt_gettoken(&timer->timer_token);
    timer->cancel = false;
    timer->running = false;
    timer->active = true;
    timer->gd = mycpu;
    systimer_init_oneshot(&timer->st, __hrtimer_function, timer,
        timer->timeout_us);    // ← line 115: no prior systimer_del!
    lwkt_reltoken(&timer->timer_token);
}
```

`systimer_init_oneshot()` at `kern_systimer.c:360` does `bzero(info, sizeof(struct systimer))`
which zeroes the `TAILQ_ENTRY` linkage fields of `timer->st`. If `timer->st` was already
enqueued in a per-CPU systimer queue (from a previous `hrtimer_start` call), this `bzero`
**corrupts the queue** by severing the linked-list node without removing it from the queue.

Effects:
- The per-CPU systimer list is corrupted (dangling pointers in TAILQ)
- The old systimer entry is orphaned (may fire with garbage data)
- Subsequent systimer operations on that CPU may panic or loop

This happens whenever `hrtimer_start` is called on a timer that's already armed — e.g.
re-scheduling a display vblank timer or a hardware poll timer.

## Primitive
- Class: memory corruption (per-CPU systimer queue corruption via bzero of linked node)
- Corrupts `TAILQ_ENTRY` links → linked list corruption → potential arbitrary code execution
  when the corrupted list is traversed

## Fix
`fix.diff`: Call `systimer_del(&timer->st)` before `systimer_init_oneshot()` if the timer
was previously active:
```c
if (timer->active)
    systimer_del(&timer->st);
```
