DragonFlyBSD Kernel Audit
DF-2867 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-2867",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "leak",
  "confidence": "certain",
  "verdict": "On the stock X86_64_GENERIC kernel an unprivileged user (uid 1001) ktrace(2)s their own process with KTRFAC_SYSCALL and issues raw 7-arg mmap(2) syscalls with the stack-passed 7th argument in a PROT_NONE page. syscall2()/sys_xsyscall() copy only regcnt words into sysmsg.extargs, fail the copyin of the remainder, and STILL call ktrsyscall() with the full narg; kern_ktrace.c:127-132 copies all narg words into the KTR_SYSCALL record appended to the user-readable trace file. Fault records verbatim echo a groom value that was never fetched (mechanism proof) and, in a loop, 391-393/404 samples are kernel-canonical (0xffff...) kernel-stack/heap pointers varying per boot (e.g. 0xfffff80117e579e0, 0xfffff8008f842dc0, above kernel _end 0xffffffff81b25e40). Repeatable across 3/3 runs; no privileges; no crash. fix.diff (bzero of the unfetched extargs tail at pc64 direct+indirect and vkernel64 sites) was applied in-guest, rebuilt with make nativekernel (rc=0, -Werror), installed and booted: identical PoC then shows fault records arg7=0, groom_echoed=0, kernel-canonical=0, exit 1 (RESULT: NOT reproduced). Baseline vs patched fully logged.",
  "exploit_chain": "unpriv user -> ktrace(2) on own pid (ktrcanset self-grant, kern_ktrace.c:668-684) -> raw mmap (SYS_mmap=197, 7 args, mmap_args sysproto.h:530) with arg7 fetched from unmapped user stack -> trap.c:1243 copyin fails -> trap.c:1248-1250 ktrsyscall(lp,197,7,&sysmsg.extargs) with extargs[6] uninitialized -> kern_ktrace.c:131-132 copies it into ktr_syscall.ktr_args[6] -> ktrwrite() appends to /tmp/df2867.trace owned by the attacker -> attacker reads stale kernel stack (kernel pointers) at will; indirect path (regcnt=5) leaks 2 words.",
  "evidence": [
    "run1.log.txt lines [000]-[003]: groom 0xaaaa0000deadaa7f echoed by the faulting record [001] that never fetched arg7; [013]+ 0xfffff80117e579e0 kernel-canonical",
    "run1/2/3.log.txt summary: total=404 nonzero=404 groom_echoed=11-13 kernel-canonical=391/392/393, RESULT: LEAK REPRODUCED",
    "fix/patched_run1-3.log: fault records arg7=0x0000000000000000, summary nonzero=2 groom_echoed=0 kernel-canonical=0, RESULT: NOT reproduced",
    "fix/build_reboot.log: nativekernel RC=0, installkernel completed Wed Sep 2 15:32:18 UTC 2026, booted #1 Wed Sep 2 15:21:48 UTC 2026, bzero fix present at /usr/src trap.c:1242,1423 + vkernel64 trap.c:1081"
  ],
  "kernel_refs": [
    "sys/kern/kern_ktrace.c:111-137",
    "sys/kern/kern_ktrace.c:127-132",
    "sys/platform/pc64/x86_64/trap.c:1236-1253",
    "sys/platform/pc64/x86_64/trap.c:1415-1436",
    "sys/platform/vkernel64/x86_64/trap.c:1075-1094",
    "sys/sys/sysproto.h:530-538",
    "sys/kern/init_sysent.c:214"
  ],
  "poc_changes": "No prior seed (first pack for this finding). Fixed during bring-up: (1) added sys/param.h + sys/mman.h includes for MAXCOMLEN/mmap constants; (2) parser arg offset 4 -> 8 (register_t 8-byte alignment inside struct ktr_syscall pads 4 bytes after the two shorts); (3) after fix-validation exposed an exit-code ambiguity, groom-echo counting tightened to exclude the two legit groom records (samples[0]/[2]).",
  "attempts": 3,
  "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": 2280,
  "guest_dirty": 0,
  "build_cmd": "cd /tmp && cc -O2 -Wall -o ktrleak ktrleak.c",
  "run_cmd": "cd /tmp && ./ktrleak   (as unpriv user maxx uid=1001)",
  "code_hash": "e60b6c5a2d4cc7f24b3b4ff0b03e8817be01ded663a330c0ec92e3410b83ddaf",
  "notes": "Baseline on stock kernel #0 (Jul 2); fix validated on rebuilt kernel #1 (Sep 2 15:21:48). 7-arg syscalls: mmap(197), sendfile(393), mountctl(468), vmspace_mmap(489); indirect syscall() path leaks 2 words (extargs[5..6]). Guest /tmp build logs lost at reboot (tmpfs); RC lines captured live and recorded in fix/build_reboot.log. Guest reset to clean-source snapshot after validation. DF-0101/0102 cover other uninit bytes in the same record family - different root cause (fetch-error path) and much larger disclosure (full stale stack words).",
  "recommended_fix": "bzero the unfetched tail of sysmsg.extargs (argsdst[regcnt..narg)) right after the register-arg bcopy at all three syscall-arg fetch sites (pc64 syscall2 + sys_xsyscall, vkernel64 syscall2) before attempting copyin - see fix.diff.",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Wed Sep  2 15:21:48 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Applied fix.diff in guest /usr/src, make -j6 nativekernel KERNCONF=X86_64_GENERIC rc=0 (-Werror), make installkernel rc=0, rebooted into kernel #1 (Sep 2 15:21:48). Exact PoC re-run 3x: faulting records now carry arg7=0 (no groom echo), nonzero=2 (only legit groom records), kernel-canonical=0, RESULT: NOT reproduced, exit 1. Baseline (stock #0) simultaneously shows 404/404 nonzero with 391-393 kernel-canonical and groom echo. Leak eliminated by the fix.",
  "fix_evidence": [
    "fix/patched_run1.log",
    "fix/patched_run2.log",
    "fix/patched_run3.log",
    "fix/build_reboot.log",
    "run1.log.txt (baseline contrast)"
  ]
}