DF-2667 / verdict.json
{ "finding_id": "DF-2667", "status": "reproduced", "reproduced": 1, "impact": "panic", "confidence": "certain", "verdict": "Unprivileged (uid 1001, non-jailed) local kernel panic reproduced on the stock INVARIANTS guest with a single mountctl(\"/\", MOUNTCTL_MOUNTFLAGS, -1, NULL, 0, NULL, 0) syscall: sys_mountctl() skips the privilege check for MOUNTCTL_MOUNTFLAGS (sys/kern/vfs_syscalls.c:1281-1285), forwards a NULL result buffer when buflen==0 (:1311-1312), and vfs_flagstostr() executes strlen(buf) at sys/kern/vfs_subr.c:1996 BEFORE its degenerate 0-length guard (:2004-2007), faulting at address 0x0 (console: 'Fatal trap 12 ... fault virtual address = 0x0', 'Stopped at strlen: cmpb $0,(%rdi)', faulting process df2667). NULL-page read only: the ceiling is a reliable unprivileged DoS, no escalation path. fix.diff moves the NULL/zero-length rejection ahead of the strlen(); validated on a rebuilt kernel (#1): the same syscall returns EINVAL and the guest stays up, while a proper 256-byte buffer still returns the flags string ('local') — no regression.", "exploit_chain": "", "evidence": ["run.log (unprivileged run + console panic text)", "panic.txt (Fatal trap 12, fault address 0x0, Stopped at strlen, from df2667)", "fix_validation.log + run.patched.log (patched kernel returns EINVAL, positive control works)", "fix.diff"], "kernel_refs": ["sys/kern/vfs_syscalls.c:1281", "sys/kern/vfs_syscalls.c:1292", "sys/kern/vfs_syscalls.c:1311", "sys/kern/vfs_default.c:1316", "sys/kern/vfs_subr.c:1996", "sys/kern/vfs_subr.c:2004"], "poc_changes": "PoC written fresh for this finding (no seed); raw syscall stubs used because libc does not export mountctl(); syscall number 468 taken from sys/sys/syscall.h and verified in-guest.", "attempts": 1, "guest_uname": "DragonFly dfbsd 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": 12, "guest_dirty": 0, "build_cmd": "cc -O -o /tmp/df2667 /tmp/mountctl_null.c", "run_cmd": "/tmp/df2667 (as unprivileged user maxx, uid 1001)", "code_hash": "d61a180ccbe06cf956837498c08895700a52be9828df5ffa2643b3f338dd3e4e", "notes": "Guest was reset with-src after the panic; fix validated on rebuilt kernel #1 (fix built together with DF-2668's fix in one kernel); guest reset again after validation. Not memory corruption (NULL-page read), so no escalation attempted.", "recommended_fix": "In vfs_flagstostr(), reject buf == NULL || len == 0 before strlen(buf) (see fix.diff).", "fix_status": "fixed", "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Sun Aug 30 10:16:19 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "Patched kernel returns EINVAL for the degenerate mountctl instead of panicking; positive control (valid 256-byte buffer) still returns the flags string; guest stable.", "fix_evidence": ["fix_validation.log", "run.patched.log", "fix.diff"] } |