⬢ DragonFlyBSD Kernel Audit
DF-5801 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5801",
  "status": "reproduced",
  "reproduced": true,
  "impact": "none",
  "confidence": "certain",
  "verdict": "vm_page_bits() (sys/vm/vm_page.c:3905-3923) validates its (base,size) arguments only with a KASSERT, which is compiled out in release kernels (sys/sys/systm.h:116-119); out-of-page arguments reach the function completely unvalidated (proved on the guest: KLD rig arguments 0/8192 appear verbatim in the INVARIANTS panic message with rig_loader in the backtrace, reproduced on two boots). In a release build the same input silently computes (2<<last_bit)-(1<<first_bit): 0xFFFF for (0,8192), phantom bit-8 0x100 for (4096,1), and shift/signed-overflow UB for negative or oversized arguments (documented with the guests own cc in bitsarith.log); the mask feeds the uint8_t m->valid/m->dirty setter family, where out-of-page ranges silently over-mark whole pages valid (stale-data direction) and confuse int-sized consumers (kern/vfs_bio.c:4100). A pass-3 sweep of every in-tree caller found all currently bounded, so no security impact is demonstrated - filed as Info hardening. fix.diff (unconditional clamp before the KASSERT) was validated on the guest with a single-fix nativekernel build: baseline rig panicked twice; patched kernel loads the rig with no panic and clamped masks (0/8192->0xff, 4096/1->0x0, -512/1024->0x3), guest stays up.",
  "exploit_chain": "",
  "evidence": "panic.txt (two identical INVARIANTS panics, args echoed); bitsarith.log (release-build masks on guest cc 8.3 -O2); fix_run.log (patched kernel #1 Mon Oct 12 22:33:20 UTC 2026: LOADED-OK, kldstat pqb_rig.ko, all RIG lines with clamped values); fix.diff (git-apply clean); pqb_bits_rig.c (rig source, sha256 b9a6e71e94a376110d6f9dd6e28ec3bd9bd0d27469a01dc66bac16bdb7632236)",
  "kernel_refs": [
    "sys/vm/vm_page.c:3905",
    "sys/vm/vm_page.c:3922",
    "sys/vm/vm_page.c:3999",
    "sys/vm/vm_page.c:4018",
    "sys/vm/vm_page.c:4038",
    "sys/vm/vm_page.c:4060",
    "sys/vm/vm_page.c:4102",
    "sys/sys/systm.h:116",
    "sys/vm/vm_page.h:197",
    "sys/kern/vfs_bio.c:4100"
  ],
  "poc_changes": "Rig authored fresh for pass 3 (no seed). Had to route source transfer via guest HTTP fetch (10.0.2.2) because the guest lacks base64(1) and long ssh one-liners truncate; fix-build switched from buildkernel (blocked: must buildworld first) to make nativekernel KERNCONF=X86_64_GENERIC.",
  "attempts": 3,
  "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 (baseline); #1: Mon Oct 12 22:33:20 UTC 2026 (single-fix kernel)",
  "runtime_sec": 4200,
  "guest_dirty": 0,
  "build_cmd": "sh build.sh  (guest: cd /root/df5801 && make; KLD pqb_rig.ko)",
  "run_cmd": "sh run.sh   (guest: kldload pqb_rig.ko)",
  "code_hash": "b9a6e71e94a376110d6f9dd6e28ec3bd9bd0d27469a01dc66bac16bdb7632236",
  "notes": "Caller sweep bounding every in-tree vm_page_bits/setter call site: kern/uipc_syscalls.c:1771-1807, kern/vfs_helper.c:346-354, vm/vm_fault.c:3328-3330, kern/vfs_bio.c:377,2510-2517,4096-4149, vfs/devfs/devfs_vnops.c:2206-2216, vfs/smbfs/smbfs_io.c:494 - all bounded, hence Info. Guest left clean (vm.sh reset with-src after fix validation).",
  "recommended_fix": "Clamp base/size unconditionally to the page in vm_page_bits() before the KASSERT (see fix.diff).",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "Single-fix kernel (fix.diff applied to guest /usr/src, make nativekernel KERNCONF=X86_64_GENERIC, installkernel, reboot into #1 Mon Oct 12 22:33:20 UTC 2026): the baseline rig - which panicked the unpatched INVARIANTS kernel twice with vm_page_bits: illegal base/size 0/8192 - now loads cleanly (kldstat shows pqb_rig.ko), every RIG line prints, masks are clamped to the page (0/8192->0xff, 4096/1->0x0, -512/1024->0x3, no UB), legal in-page behavior unchanged (0/4096->0xff), and the guest remains up. fix_patched_reproduced=false reflects that the *bad* behavior (panic/silent OOB masks) is GONE on the patched kernel, which is the success criterion.",
  "fix_evidence": "fix_build.log (patch check + nativekernel NK-OK + installkernel), fix_run.log (patched uname, LOADED-OK, kldstat, clamped RIG output), fix.diff (sha256 be64ae3e7b973623494fa99688014414084a262e697147e652aadf6fd3a3a604), panic.txt (baseline A/B)"
}