{
  "finding_id": "DF-2685",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "REPRODUCED on stock DragonFly 6.5-DEVELOPMENT #0 (X86_64_GENERIC): mlock() on swapped-out anonymous memory returns success but presents ZERO-FILLED pages (16,253,937 of 16,777,216 words destroyed in the decisive run; 16,340,977 in the first run). Root cause: TRYPAGER() (sys/vm/vm_fault.c:383-385) disables the pager for ALL VM_FAULT_WIRE_MASK faults, so vm_fault_object() never calls vm_pager_get_page() for wiring faults and instead zero-fills a fresh page at vm_fault.c:2327 and pmap_enter()s it wired. POSIX mlock semantics (pages become resident WITH their contents) are violated with fully silent data destruction. On stock x86-64 the mlock syscall is SYSCAP_RESTRICTEDROOT-gated (vm_mmap.c:1029-1035), so the direct victim population is privileged software that wires memory (key-holding daemons, mlockall services, NVMM guest RAM via vm_map_kernel_wiring, brk under MAP_WIREFUTURE) precisely when a local user has forced the box into swap pressure; no error is reported anywhere. FIX VALIDATED: with TRYPAGER allowing VM_FAULT_USER_WIRE, rebuilt kernel (#1 Aug 30 19:03:41) returns 'OK: data intact after mlock' (bad=0, rc=0) under equivalent swap pressure (1121MB swapped vs 1026MB baseline).",
  "exploit_chain": "Local unprivileged user allocates ~4.6GB on a 4GB box driving a privileged mlock-using process's pages to swap; the privileged process (re)locks its memory via mlock/mlockall; the kernel zero-fills the locked region instead of paging it in (vm_fault.c:2327 via TRYPAGER exclusion at vm_fault.c:383-385); key material / auth state / database buffers silently become zeros -> authentication breakage, permanent data loss, availability collapse of the locking process. Not a kernel memory-corruption primitive; no kernel-memory disclosure or overwrite; impact is silent user-memory destruction (integrity/availability) in privileged processes.",
  "evidence": [
    "findings/poc/DF-2685/baseline_stock_run.log - stock run: swapinfo 1026M used, mismatch lines, 'bad=16253937 of 16777216 words', 'BUG REPRODUCED', rc=2",
    "findings/poc/DF-2685/patched_run.log - patched kernel: swapinfo 1121M used, 'bad=0 of 16777216 words', 'OK: data intact after mlock', rc=0",
    "findings/poc/DF-2685/build.log - validated kernel identity (#1 Aug 30 19:03:41), build/install record, patch verification",
    "findings/poc/DF-2685/VERDICT.md - full line-level trace: sys/vm/vm_mmap.c:1036 -> vm_map.c:2654 -> vm_fault.c:2632 -> TRYPAGER vm_fault.c:383-385 -> zero_fill vm_fault.c:2327 -> pmap_enter vm_fault.c:793"
  ],
  "kernel_refs": [
    "sys/vm/vm_fault.c:383", "sys/vm/vm_fault.c:2327", "sys/vm/vm_fault.c:2632",
    "sys/vm/vm_map.c:2654", "sys/vm/vm_mmap.c:1029", "sys/vm/vm_mmap.c:1036",
    "sys/vm/vm_unix.c:151", "sys/dev/virtual/nvmm/nvmm_dragonfly.c:193"
  ],
  "poc_changes": "Self-written for this verification (no seed). Pattern-based verifier with page-index-derived words; 4.6GB churn against 4GB RAM + 4GB swap; verifies 64MB earliest-swapped region after mlock. Also probed: file-backed mlock (masked while pages resident), unprivileged reachability (EPERM from SYSCAP_RESTRICTEDROOT on x86-64 stock, documented).",
  "attempts": 4,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026  root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "runtime_sec": 1450,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -o /tmp/mt/mlockswap mlockswap.c   (fix kernel: cd /usr/src && patch -p1 < fix.diff && make -j4 nativekernel && make installkernel && reboot)",
  "run_cmd": "/tmp/mt/mlockswap   (baseline: rc=2 'BUG REPRODUCED'; patched: rc=0 'OK: data intact after mlock')",
  "code_hash": "23574fbe1562edd1549c3d79cb9bbd489c57e0e7a55133b33602f69625a508e1",
  "notes": "First reproduction (previous boot): bad=16340977. Kernel-wiring (VM_FAULT_CHANGE_WIRING) still skips the pager after the fix (historical deadlock avoidance); NVMM vm_map_kernel_wiring of guest RAM remains exposed - residual hardening noted. The mlock EPERM gate for plain users is itself a DFly x86-64 quirk (#ifdef pmap_wired_count); on configurations where only RLIMIT applies, any user triggers directly.",
  "recommended_fix": "TRYPAGER must not exclude user-wiring faults from the pager: allow VM_FAULT_USER_WIRE so mlock/mlockall page data in instead of zero-filling (see fix.diff).",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Sun Aug 30 19:03:41 UTC 2026  root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Baseline reproduced on stock #0 (16.25M words zeroed, rc=2). Patched kernel #1 with the one-macro TRYPAGER fix returns bad=0 / rc=0 under equivalent swap pressure (1121MB swapped at verify time). Bad behavior eliminated; data paged back in correctly.",
  "fix_evidence": "findings/poc/DF-2685/patched_run.log; findings/poc/DF-2685/build.log"
}
