DF-3198 / verdict.json
{ "finding_id": "DF-3198", "status": "reproduced", "reproduced": 1, "impact": "panic", "confidence": "certain", "verdict": "devfs_rule_reset_node() calls devfs_gc() while devfs_iterate_topology() holds saved TAILQ cursors; devfs_gc frees arbitrary nodes (links to the target, empty dirs), so the walker revisits freed memory. With a rule-built chain L2->L1->null, DEVFS_RULE_RESET panicked deterministically: assertion node->link_target failed in devfs_rule_reset_node at devfs_rules.c:223 with the full stack through devfs_iterate_topology <- devfs_apply_reset_rules_caller. On non-INVARIANTS kernels the next statement is a write through the NULL link_target (low-page fault), and the stale ORPHANED/list state drives orphan-list and child-list corruption routed through freed memory.", "exploit_chain": "privileged (root, or jailed root via DF-3197) ioctl sequence: ADD LINK null->L1, ADD LINK L1->L2, APPLY *, RESET * -> devfs core thread frees L2 during L1s gc -> reset_node runs on freed L2 -> KKASSERT/NULL-page write; production kernels get list corruption through the freed chunk (double-unlink of orphaned nodes)", "evidence": [ "panic.txt: assertion + full backtrace", "run.log: chain built then panic on RESET", "run.fixed.log: SURVIVED, links cleaned, guest up" ], "kernel_refs": [ "sys/vfs/devfs/devfs_rules.c:222", "sys/vfs/devfs/devfs_rules.c:226", "sys/vfs/devfs/devfs_core.c:630", "sys/vfs/devfs/devfs_core.c:721", "sys/vfs/devfs/devfs_core.c:1912" ], "poc_changes": "none beyond compile fixes (limits.h include)", "attempts": 1, "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": 8, "guest_dirty": 1, "build_cmd": "cc -static -O -o uaf_reset uaf_reset.c", "run_cmd": "./uaf_reset", "code_hash": "a4b660fb090e0bffd8385f3516b7675aa12d60c3c88cd57586156a0f0f372a73", "notes": "trigger is privileged; combined with DF-3197 it is a jailed-root -> host-kernel-corruption path. memcorrupt bucket.", "recommended_fix": "two-pass reset: unlink+collect rule-created links during the walk, free (gc_links + freep + one gc_dirs sweep) only after it", "fix_status": "fixed", "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Tue Sep 8 10:25:07 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "same PoC on the fixed kernel: SURVIVED, /dev/L1 and /dev/L2 removed by the reset, tree consistent, guest stayed up", "fix_evidence": [ "DF-3198/run.fixed.log" ] } |