vm_contig_pg_clean color-queue validation is provably wrong: reclaims only color-0 pages, skipping 1023/1024 page queues β contigmalloc reclaim flush is ~99.9% ineffective
| Field | Value |
|---|---|
| ID | DF-2889 |
| Status | new |
| Severity | Low |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L |
| CWE | CWE-670 Always-Incorrect Control Flow |
| File | sys/vm/vm_contig.c |
| Lines | 194 (callers :339-343, :355-361) |
| Area | vm |
| Confidence | certain |
| Discovered | 2026-09-02 |
| Pass | 2 (GLM 5.3 second pass) |
| Bucket | base:vm |
| Reported | pending |
| Known CVE | none |
| CVE match | novel |
Summary
After busying a page, vm_contig_pg_clean re-validates with
if (m->queue - m->pc != queue). Pages are always enqueued on
PQ_base + m->pc with m->pc &= PQ_L2_MASK, so for any page on queue
PQ_INACTIVE+q, m->queue - m->pc == PQ_INACTIVE β which equals queue
(PQ_INACTIVE + q) only when q==0. The intended check was
m->queue != queue (correctly asserted at :176). Net effect: both
callers loop q=0..1023 but every queue with q>0 is walked page-by-page
(spinlocks + busy_try + wakeup per page) with ZERO pages reclaimed β
only color-0 pages are ever cleaned. Large contigmalloc allocations
(DRM/agp/netmap/nvmm) fail far more often than designed; each failed
pass still performs the full slow walk of every page in every queue
("very, very slow" per the code's own comment), stalling all
contigmalloc callers three times including M_NOWAIT ones β a local
availability amplification for any user-reachable contigmalloc path
(netmap/GPU ioctls). Fix: m->queue != queue (one-line, row diff).
Timeline
- 2026-09-02 Discovered during pass-2 audit of vm_contig.c (GLM 5.3).
No comments yet.