hrtimer_start_range_ns corrupts per-CPU systimer queue by calling systimer_init_oneshot without prior systimer_del on an armed timer
Summary
hrtimer_start_range_ns calls systimer_init_oneshot(&timer->st,...) at line 115 without first calling systimer_del to remove any previously-armed systimer from per-CPU queue. systimer_init_oneshot (kern_systimer.c:363) executes bzero(info sizeof(struct systimer)) which zeroes TAILQ_ENTRY(node) linkage and SYSTF_ONQUEUE flag while systimer may still be linked into gd->gd_systimerq. Neighboring queue entries retain stale tqe_next/tqe_prev pointers to this entry creating corrupted doubly-linked list causing infinite loops NULL dereferences or stale-pointer traversals in systimer_intr. systimer_add KKASSERT((info->flags & SYSTF_ONQUEUE)==0) PASSES because flags just zeroed masking corruption. Triggered by any caller invoking hrtimer_start on timer whose systimer currently armed. i915 forcewake path concrete trigger: fw_domain_arm_timer (intel_uncore.c:74-81) calls hrtimer_start_range_ns unconditionally whenever wake_count drops to 0 without checking if timer already armed. During normal GPU operation forcewake get/put cycles complete well within 1ms timeout causing arm_timer while previous systimer still on queue. Attacker local access to i915 hardware triggers via any GPU operation requiring forcewake. Impact: corrupted systimer queue causes systimer_intr infinite-loop (system hang) NULL-deref (kernel panic) or traverse stale pointers into freed/reused memory (corruption potential code execution).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2175 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | verdict | source-level analysis with path:line citations | 1.9 KB | β raw |
| reachability.txt | environment | guest PCI/device survey proving no required HW | 1.6 KB | view raw |
| fix.diff | suggested-fix | git-apply-able fix (validated: applies clean) | 328 B | view raw |
| build.sh | build-log | documents HW requirement | 550 B | view raw |
| run.sh | run-log | documents HW requirement | 272 B | view raw |
| env.txt | environment | guest uname and environment | 491 B | view raw |
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:
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_ENTRYlinks β 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:
if (timer->active)
systimer_del(&timer->st);
Fix verification
not_testablegit apply --check clean + drm.ko compiles
git apply --check clean + drm.ko compiles
Confirmed kernel references
β
Detail
Exploit chain
none (HW-gated)
Evidence (decisive lines)
HW-GATED (no GPU). Source-confirmed: hrtimer_start_range_ns systimer_init_oneshot without prior systimer_del -> bzero of queued systimer TAILQ_ENTRY -> queue corruption.
Verified recommended fix
HW-GATED (no GPU). Source-confirmed: hrtimer_start_range_ns systimer_init_oneshot without prior systimer_del -> bzero of queued systimer TAILQ_ENTRY -> queue corruption.
Verdict
HW-GATED (no GPU). Source-confirmed: hrtimer_start_range_ns systimer_init_oneshot without prior systimer_del -> bzero of queued systimer TAILQ_ENTRY -> queue corruption.
No comments yet.