DF-5801 / verdict.json
{ "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)" } |