bsd4_kick_helper issues IPIs/wakeups while holding the global bsd4_spin: FIFO-full liveloop enables same-cpu schedclock recursion into the spinlock (whole-system wedge), unprivileged-triggerable when usched_bsd4 is active
| Field | Value |
|---|---|
| ID | DF-2712 |
| Status | new |
| Severity | Medium |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:H |
| CWE | CWE-667 Improper Locking, CWE-834 Deadlock |
| File | sys/kern/usched_bsd4.c |
| Lines | 1590-1615 (kick_helper), calls 1473/1512/1519/1561 under spin 533/1780 |
| Area | kern |
| Confidence | likely |
| Discovered | 2026-08-30 |
| Pass | 2 (GLM 5.3 second pass) |
| Bucket | base:kern |
| Reported | pending |
| Known CVE | none |
| CVE match | novel |
Summary
bsd4_chooseproc_locked_cache_coherent() runs under the single global scheduler spinlock and calls bsd4_kick_helper() up to queue_checks (default 5) times per invocation; kick_helper executes lwkt_send_ipiq()/wakeup() while its caller still holds bsd4_spin (its own comment admits it). Every other IPI site in this file unlocks first, and usched_dfly.c explicitly documents the discipline. When the per-cpu ipiq FIFO exceeds MAXCPUFIFO−3 = 253 entries, lwkt_send_ipiq3 enables interrupts and liveloops waiting for the target to drain — still holding bsd4_spin. Two wedge modes: (a) same-cpu schedclock → bsd4_resetpriority → recursive spin_lock on a non-reentrant lock in interrupt context (no self-hold detection; indefinite_check only prints) — the interrupt never returns and every other cpu wedges on the next scheduler touch: whole-system hang without a panic; (b) cross-cpu mutual wedge via a target blocked in a critical section on bsd4_spin stopping its FIFO drain. An unprivileged user with many runnable threads pinned across cpus multiplies the IPI fill rate of every scheduling event.
Threat model & preconditions
Unprivileged local user on a system booted with
kern.user_scheduler=bsd4 (or a privileged proc switched to bsd4):
persistent whole-system DoS. Latent on stock dfly boots (code dormant);
not memory corruption — the ceiling is availability.
Recommended fix
Move all IPI/wakeup issuance out from under bsd4_spin (deferred-kick variant: record targets under the spin, unlock, then issue) — matching the file's own discipline at :882-896 and dfly's design. Guardrails: clamp usched_bsd4_queue_checks ≥ 1 (also closes DF-0019) and validate rrinterval to [1, SHRT_MAX]. Phase V skipped per conditional policy (Medium, latent-config DoS); trigger sketch in the file row.
Timeline
- 2026-08-30 Discovered during pass-2 audit of usched_bsd4.c (GLM 5.3).
No comments yet.