# DF-2689 VERDICT — leftover DEBUG kprintf in vm_pageout_scan_hold

**Status: untested (Info hardening finding; source-certain, no guest run needed).**

## Root cause

`sys/vm/vm_pageout.c:1932` — an unconditional `kprintf("DEBUG: pageout
HOLD->FREE %p\n", m)` sits on the normal recovery path of
`vm_pageout_scan_hold()`. The scanner exists to clean the benign race
residue documented in `vm_page_unhold()` (sys/vm/vm_page.c:1403-1410): a
`vm_page_free*()` moving a held page to PQ_HOLD can interleave with the
holder's final unhold, leaving the page on PQ_HOLD with `hold_count == 0`.
The scanner detects exactly that case and "reprocesses" it with a
hold/unhold cycle — that case is the *expected* input of this scanner, yet
it prints a debug line with a raw kernel pointer each time.

## Verification of the surrounding logic (cross-check requested by the audit)

- The hold→unhold "reprocess" is safe: `vm_page_hold()` only asserts the
  page is not on PQ_FREE (vm_page.c:1392-1396); a PQ_HOLD page with
  `hold_count == 0` and `m->object == NULL` (already removed by
  `vm_page_free_toq` → `vm_page_remove`, vm_page.c:3186) has no possible
  concurrent legitimate holder, and the final `vm_page_unhold()` re-tests
  `hold_count == 0 && queue == PQ_HOLD` under the page and queue spinlocks
  before moving it to PQ_FREE (vm_page.c:1420-1428).
- The queue-spinlock drop/re-acquire around the unhold (:1934-1936) is
  required because unhold may take the page and queue spinlocks itself;
  no marker protocol violation results (marker advanced past `m` before
  unlocking; PG_MARKER pages skipped at :1924).
- Conclusion: logic correct, print is pure leftover debug output.

## Impact

Info. Console/message-buffer spam on a path reachable from unprivileged
memory-pressure workloads, plus kernel pointer disclosure (CWE-532) to
local users via readable message buffer; pointer disclosure matters mainly
as a KASLR defeat on hardened deployments.

## Why not run on the guest

The finding is a static one-line defect; the PQ_HOLD residue race that
triggers the print is rare and non-deterministic, and demonstrating log
spam adds no evidence beyond the source itself. Guest left untouched.

## Fix

`fix.diff`: remove the kprintf. (Alternative if ever desired for triage:
gate it behind `vm_pageout_debug` like the other debug prints in this file.)
