DF-2759 / verdict.json
{ "finding_id": "DF-2759", "status": "reproduced", "reproduced": 1, "impact": "leak", "confidence": "certain", "verdict": "Reproduced on the stock guest kernel (X86_64_GENERIC, which ships options UCONSOLE at sys/config/X86_64_GENERIC:36). Unprivileged uid-1001 ioctl(TIOCCONS) succeeds because the caps_priv_check gate is compiled out (sys/kern/tty.c:969-976); constty then points at the attacker's pty and subr_prf.c's kputchar (subr_prf.c:396-405) + constty_daemon (subr_prf.c:913-985) stream all kernel messages to it, while cnwrite (tty_cons.c:465) redirects /dev/console writes there too. Demonstrated live: root console markers arriving on the unprivileged pty both instantly and as <118>-tagged constty_daemon msgbuf copies; a pure kprintf (tap0 attach) delivered; and delivery continuing after security.unprivileged_read_msgbuf=0 while the same user's dmesg gets EPERM โ a direct bypass of the admin knob, and with ptr_restrict=0 default it is a live collection channel for the entire %p kernel-pointer leak population (DF-2736/2614/2637 consumer side).", "exploit_chain": "unpriv user: posix_openpt -> ioctl(slave, TIOCCONS, 1) [no privilege needed under UCONSOLE] -> read(master): real-time full kernel-log stream incl. every %p pointer print; persists silently after the user locks dmesg via security.unprivileged_read_msgbuf=0. Pointer values feed KASLR/heap-layout disclosure for any companion memory-corruption bug.", "evidence": [ "run.log: '[0.00] TIOCCONS: SUCCESS - constty now points at this UNPRIVILEGED pty' (uid=1001)", "run.log: [3.56] '<118>DF2759-MARKER1-direct+daemon' โ constty_daemon msgbuf copy (pri tag from msglogchar subr_prf.c:1014-1023)", "run.log: dmesg EPERM + [8.56] '<118>DF2759-MARKER2-after-msgbuf-locked' โ security.unprivileged_read_msgbuf bypass", "run.log: 'tap0: MAC address: ...' โ pure kprintf content delivered to the unpriv pty", "run_patched.log: 'TIOCCONS FAILED: Operation not permitted' on the fix.diff kernel; root cross-check still succeeds", "env.txt: ptr_restrict=0 default confirmed live; uname shows X86_64_GENERIC" ], "kernel_refs": [ "sys/config/X86_64_GENERIC:36", "sys/kern/tty.c:962-980", "sys/kern/subr_prf.c:396-405", "sys/kern/subr_prf.c:913-985", "sys/kern/subr_prf.c:1014-1023", "sys/kern/subr_prf.c:1134-1143", "sys/kern/subr_prf.c:121", "sys/kern/tty_cons.c:460-477" ], "poc_changes": "Seed PoC was written fresh for this finding (no prior draft): posix_openpt/grantpt/unlockpt pty setup, raw termios on the slave to avoid echo/CR mangling, TIOCCONS with int 1, poll+read loop on the master with monotonic timestamps so the direct-forward vs delayed daemon copies are distinguishable.", "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": 2740, "guest_dirty": 0, "build_cmd": "vm.sh run_user 'cd /tmp/df2759 && cc -O -Wall -o uconsole_grab uconsole_grab.c'", "run_cmd": "sh findings/poc/DF-2759/run.sh", "code_hash": "35ee5c6e9b9b93731dc83b0eb05a5f27f5f433b92f5411a1f4aa363f306bd6ff", "notes": "Fixed-kernel uname: 'DragonFly dfbsd 6.5-DEVELOPMENT #1: Mon Aug 31 21:24:15 UTC 2026'. Guest was reset with-src after validation (guest_dirty back to 0). Killed candidates recorded in VERDICT.md: constty dangling-pointer UAF (pti/nmdm softcs never freed), uprintf/tprintf torn s_ttyp (store ordering + ttyhold), %px ptr_restrict escape (zero in-tree users), %pb%i div-by-zero (constants only), kvcprintf width int overflow (bounded sink), msgbuf clear/MP races (tolerant chunk-advance), kvsnprintf truncation (correct). Known findings not re-reported: DF-0035, DF-0036, DF-2586.", "recommended_fix": "Remove 'options UCONSOLE' from sys/config/X86_64_GENERIC and make the TIOCCONS caps_priv_check_td(SYSCAP_RESTRICTEDROOT) unconditional in sys/kern/tty.c (fix.diff, validated in-guest).", "fix_status": "fixed", "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Mon Aug 31 21:24:15 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff (config UCONSOLE removal + unconditional caps gate in tty.c) applied to guest /usr/src, nativekernel rebuilt and installed, guest rebooted into kernel #1. Identical PoC as uid 1001: TIOCCONS now fails with EPERM and no kernel content reaches the pty (run_patched.log); root TIOCCONS still succeeds โ gate restored, feature intact for privileged use.", "fix_evidence": [ "fix.diff (git apply --check clean on the audit repo)", "fix_build.log: '>>> Kernel install for X86_64_GENERIC completed' + patched-kernel uname #1", "run_patched.log: 'TIOCCONS FAILED: Operation not permitted' / zero bytes captured", "root cross-check: uid=0 TIOCCONS SUCCESS on patched kernel" ] } |