DragonFlyBSD Kernel Audit
← triage · dashboard
DF-2678

vm_page_free_contig() can leak PG_FICTITIOUS DMA-reserve pages when vm_low_phys_reserved has been lowered below the freed block

Field Value
ID DF-2678
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:N/A:L
CWE CWE-401 Missing Release of Memory
File sys/vm/vm_page.c
Lines 2868 (mutable watermark branch), 3184 (fictitious early-return)
Area vm
Confidence speculative
Discovered 2026-08-29
Pass 2 (GLM 5.3 second pass)
Bucket memcorrupt
Reported pending
Known CVE none
CVE match novel

Summary

vm_page_free_contig() decides between "return to alist" and "normal free" using pa < vm_low_phys_reserved (vm_page.c:2868), but vm_low_phys_reserved is a mutable watermark lowered by vm_page_startup_finish() (:826) as boot-time reserve pages are released. A contig block still inside the alist but above the final watermark takes the else-branch on a PG_FICTITIOUS page: vm_page_unwire is a no-op for fictitious pages and vm_page_free_toq early-returns at :3184-3188 — the page is permanently leaked from both the alist and the page queues, and v_wire_count accounting drifts.

Threat model & preconditions

In-kernel contigmalloc/contigfree users (drivers, privileged) on boot geometries where alist blocks survive above the final watermark; repeated alloc/free cycles shrink the low-DMA reserve until contigmalloc failures. No memory corruption; resource-exhaustion DoS of the DMA reserve only. Not reproduced (requires specific boot memory geometry; speculative).

--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -2865,7 +2865,7 @@ vm_page_free_contig(vm_page_t m, unsigned long size)
    vm_pindex_t start = pa >> PAGE_SHIFT;
    vm_pindex_t pages = (size + PAGE_MASK) >> PAGE_SHIFT;

-   if (pa < vm_low_phys_reserved) {
+   if (m->flags & PG_FICTITIOUS) {
        /*
         * Just assert check the first page for convenience.
         */

Timeline

  • 2026-08-29 Discovered during pass-2 audit of vm_page.c (GLM 5.3).

Discussion (0)

No comments yet.