DF-5775 / verdict.json
{ "finding_id": "DF-5775", "status": "reproduced", "reproduced": true, "impact": "dos", "confidence": "certain", "verdict": "writepid() opens the operator-supplied -p path without O_NOFOLLOW (init.c:1390) and then ftruncate(0)+write(pid) (init.c:1400-1401): a symlinked pidfile path lets the vkernel truncate and overwrite the symlink TARGET with the launching users privileges (root for production vkernels). Reproduced live: marker file replaced by the bare pid via /tmp/df5775_link, with the vkernel failing immediately after (writepid precedes -m validation, so no bootable config is needed). Fixed kernel rejects the symlink with ELOOP and the target survives.", "exploit_chain": "attacker controls a pidfile path flowing into a root-launched vkernels -p (config injection) -> plants symlink at that path pointing at the victim file -> vkernel start truncates victim to 0 and writes an 8-byte pid -> arbitrary root file destruction (CWE-59)", "evidence": "baseline_run.log (marker -> [14255], CLOBBERED via symlink, link survives); fixed_run.log (marker intact, Failed to create pidfile: Too many links)", "kernel_refs": [ "sys/platform/vkernel64/platform/init.c:1390", "sys/platform/vkernel64/platform/init.c:1400", "sys/platform/vkernel64/platform/init.c:1401", "sys/platform/vkernel64/platform/init.c:442" ], "poc_changes": "authored fresh (no seed); uses the no -m early-exit so the clobber is isolated from boot", "attempts": 2, "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": 90, "guest_dirty": 1, "build_cmd": "cd /usr/src && make -j6 nativekernel KERNCONF=VKERNEL64 (fix validation: rebuild with fix.diff hunk 3)", "run_cmd": "sh run5775.sh", "code_hash": "cfab11278da2c30a03bca56b34f4cd2d57f840474faab91e97d07a93ab414a16", "notes": "writepid runs before init_sys_memory, so the primitive fires even on non-booting invocations. cleanpid() (init.c:1406-1414) unlinks only the symlink itself.", "recommended_fix": "open the pidfile with O_NOFOLLOW added at init.c:1390", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": false, "fix_verdict": "Baseline: target truncated to pid bytes. Patched: ELOOP (Too many links), vkernel exits, target intact.", "fix_evidence": "baseline_run.log vs fixed_run.log" } |