vm.swapcache.* tunables accept unbounded/negative values, wedging the swapcache daemon state machine and burst accounting
| Field | Value |
|---|---|
| ID | DF-2840 |
| Status | new |
| Severity | Low |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:L |
| CWE | CWE-20 / CWE-670 |
| File | sys/vm/vm_swapcache.c |
| Lines | 120-153 (consumers :258-275, :290-291, :363-367) |
| Area | vm |
| Confidence | certain |
| Discovered | 2026-08-31 |
| Pass | 2 (GLM 5.3 second pass) |
| Bucket | base:vm |
| Reported | pending |
| Known CVE | none |
| CVE match | novel |
Summary
Every vm.swapcache knob is a plain CTLFLAG_RW int/quad with no validation. Negative or zero values flow straight into the daemon's hysteresis/burst/state math: accrate<0 drains curburst without bound so the SWAPB_RECOVERING gate is never satisfied and writing stops permanently; maxswappct<0 makes SWAPMAX negative so vm_swap_cache_use (unsigned) can never fall below it and the state machine wedges in SWAPC_CLEANING forever; min_hysteresis<0 breaks the clamp; maxlaunder/maxscan≤0 degenerate the scans. Root-only misconfiguration — privileged self-inflicted livelock/disable of the swap-cache accelerator. Same family as DF-2833 but distinct knobs/file.
Recommended fix
Clamp at the consumption points (accrate>0 before accumulating; maxswappct to [0,100]; min_hysteresis ≥0) — sketch diff in the row above.
Timeline
- 2026-08-31 Discovered during pass-2 audit of vm_swapcache.c (GLM 5.3).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2840 · 2 files| File | Type | Description | Size | |
|---|---|---|---|---|
| run.log | — | 260 B | view raw | |
| fix.diff | — | 1.2 KB | view raw |
Fix verification
fixedPatched kernel: with accrate=-100000 the burst accumulator no longer drains - curburst stayed at 1000000 across 12s (baseline: 1000000 -> -60000). maxswappct is clamped to [0,100] inside SWAPMAX.
df2833_2840_ab.log: curburst 1000000 stable with accrate=-100000
Confirmed kernel references
Detail
Exploit chain
root sysctl vm.swapcache.accrate=-100000 -> curburst += accrate/10 every 0.1s with no floor -> curburst crosses 0 and drains unbounded -> swapcache writing permanently halted
Evidence (decisive lines)
df2840_swapcache.log: curburst 1000000 -> 940000 -> -60000 over 20s; vm_swapcache.c:271-275,:286
PoC changes
none
Verified recommended fix
--- sys/vm/vm_swapcache.c 2026-06-29 12:51:19.000000000 +0000
Verdict
Reproduced live on the running swapcache daemon (4GB swap partition active). vm.swapcache.accrate is a plain unvalidated CTLFLAG_QUAD (sys/vm/vm_swapcache.c:148-149). Setting accrate=-100000 with data_enable=1 and curburst=1000000 drove curburst 1,000,000 -> 940,000 -> -60,000 over 20s: the burst update (:271-275) adds accrate/10 each 0.1s tick with no floor, so a negative accrate drains curburst without bound; writing halts permanently once curburst < accrate (:286) and SWAPB_RECOVERING can never be satisfied (needs curburst > minburst =10MB, unreachable while accrate<0). The maxswappct<0 wedge (SWAPMAX negative at :155-156 -> CLEANING forever at :258-264 since unsigned vm_swap_cache_use can never fall below a negative bound) is arithmetic-identical and covered by the same unvalidated-knob root cause; the accrate drain is the directly observed symptom. Root-gated self-inflicted disable of the swap-cache accelerator; knobs restored after the test.
No comments yet.