DF-4149 / verdict.json
{ "finding_id": "DF-4149", "status": "reproduced", "reproduced": 1, "impact": "dos", "confidence": "certain", "verdict": "cuse_client_read/write (cuse.c:1687-1741/1778-1832) walk uio->uio_iov directly without skipping zero-length iovs; uiomove(NULL, 0, uio) makes no progress so the loop re-issues a 0-length READ/WRITE command forever. Triggered from an unprivileged client (uid 65534) with readv(fd, [{NULL,0},{buf,8}], 2) on a world-accessible cuse device whose server replies 0. After the first signal the receive path uses uninterruptible cv_wait per round-trip, so the looping reader SURVIVES kill -9 (demonstrated: client SURVIVED SIGKILL). It is only released when the server exits (is_closing); if the stuck client also holds a /dev/cuse fd (e.g. forked from the server without O_CLOEXEC hygiene - observed during DF-4147 harness work) it stays unkillable in D-state until reboot, permanently pinning the cuse client+server kernel allocations.", "exploit_chain": "", "evidence": "run.log: [+] client uid=65534 entering readv(iov[0].len=0, iov[1].len=8) then [+] client SURVIVED SIGKILL (unkillable, stuck in cuse_client_read loop) - DoS confirmed; post-run ps showed pid 1268 in state D0 (wchan cuse-cli) persisting after the server process exited.", "kernel_refs": [ "sys/dev/misc/cuse/cuse.c:1687", "sys/dev/misc/cuse/cuse.c:1719", "sys/dev/misc/cuse/cuse.c:1778", "sys/dev/misc/cuse/cuse.c:622" ], "poc_changes": "none (first-try reproduction)", "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": 30, "guest_dirty": 0, "fix_status": "not_testable", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored (skip leading zero-length iovs in both loops, mirroring uiomove); not rebuilt on the guest - the only guest mutation budget was spent on the DF-4147 memory-corruption fix, and this Low-severity DoS fix is a two-loop mechanical change reviewed at logic level.", "fix_evidence": "fix.diff; logic-level review only", "build_cmd": "cc -O1 -Wall -o /root/cuse_zerolen /root/cuse_zerolen.c", "run_cmd": "kldload cuse; /root/cuse_zerolen", "notes": "Requires a running cuse server (webcamd etc.) and read access to its device node - the standard webcam/cuse deployment on a multi-user machine satisfies both.", "recommended_fix": "Skip zero-length iovs (advance uio_iov/uio_iovcnt) at the top of the read/write loops like uiomove() does (see fix.diff).", "code_hash": "bdee94dbe07dd4a64524dd5029254de5d7001691892fde20c0c009a36cbf9b17" } |