โฌข DragonFlyBSD Kernel Audit
DF-2759 / verdict.json
โ† back to finding โ†“ download raw
{
  "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"
  ]
}