DF-0001 / manifest.json
{ "finding_id": "DF-0001", "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly v6.5.0.1712.g89e6a-DEVELOPMENT #1: Mon Jun 29 14:18:01 UTC 2026 root@ephemeral-5c2002c44b6c:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "code_hash": "5f4b556b078fdf0307551530c159117e37a02dcb04eee1debc946826b8d0bcb6", "tested_at": "2026-07-02T00:01:06Z", "verdict": "REPRODUCED", "impact": "panic", "confidence": "certain", "reproduce": { "build": "./build.sh", "run": "./run.sh", "expected": "panic: kern_ftruncate(): VOP_GETATTR didn't return 0 ; kern_ftruncate() at kern_ftruncate+0x152 ; guest halts in DDB (db> ). Requires vfs.quota_enabled=1 (loader tunable, reboot) + options INVARIANTS (present in X86_64_GENERIC) + an ESTALE-capable GETATTR (loopback NFS with server-side fd-handle invalidation). On a non-INVARIANTS kernel the KASSERT is a no-op and ftruncate(2) just returns the GETATTR error." }, "kernel_refs": [ "sys/kern/vfs_syscalls.c:4036", "sys/kern/vfs_syscalls.c:4038", "sys/kern/vfs_syscalls.c:4111", "sys/kern/vfs_syscalls.c:4113", "sys/sys/systm.h:94", "sys/sys/systm.h:117", "sys/kern/vfs_quota.c:112", "sys/vfs/nfs/nfs_vnops.c:737", "sys/vfs/nfs/nfsm_subs.h:109" ], "artifacts": [ {"path": "estale_trig.c", "type": "trigger-source", "desc": "THE trigger that fires the panic: open fd -> server-side stale-FH invalidation -> ftruncate -> GETATTR ESTALE -> KASSERT"}, {"path": "trunc_panic.c", "type": "trigger-source", "desc": "original reviewer PoC (path truncate), sharpened to print errnos and populate the target"}, {"path": "trunc_only.c", "type": "diagnostic", "desc": "errno diagnostic proving dead-server GETATTR returns cached attrs (error=0) -> KASSERT not reached (negative evidence)"}, {"path": "build.sh", "type": "build-script", "desc": "ships sources to guest + cc as unprivileged user maxx"}, {"path": "run.sh", "type": "run-script", "desc": "full multi-step reproducer: quota reboot + loopback NFS + ESTALE handle invalidation -> panic"}, {"path": "VERDICT.md", "type": "verdict", "desc": "full mechanism walkthrough: why dead-server doesn't fire but ESTALE does, path:line at every hop"}, {"path": "README.md", "type": "readme", "desc": "human-facing build/run/preconditions + file index"}, {"path": "fix.diff", "type": "suggested-fix", "desc": "git-apply-able: KASSERT -> proper error-return + cleanup (vn_unlock+goto done for ftruncate); applies cleanly to sys/kern/vfs_syscalls.c"}, {"path": "panic.txt", "type": "panic-signature", "desc": "serial-console panic: kern_ftruncate(): VOP_GETATTR didn't return 0 at kern_ftruncate+0x152"}, {"path": "run.log", "type": "run-log", "desc": "decisive confirmation run (fresh vm.sh reset), step-by-step, full output"}, {"path": "boot.log.full", "type": "serial-log", "desc": "full untrimmed serial log of the panicking boot"}, {"path": "build.log", "type": "build-log", "desc": "final successful build of estale_trig on guest"}, {"path": "env.txt", "type": "environment", "desc": "uname, cc, quota default, INVARIANTS check (KASSERT strings in kernel binary)"}, {"path": "manifest.json", "type": "manifest", "desc": "this catalog"} ] } |