DragonFlyBSD Kernel Audit
DF-2695 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-2695",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "leak",
  "confidence": "certain",
  "verdict": "Unprivileged kernel-stack info leak reproduced: sendfile(2) failing on an early-error path (bad socket fd, non-stream socket, unconnected socket, negative offset) copies out the never-initialized local 'off_t sbytes' (uipc_syscalls.c:1594) to the user's *sbytes pointer on every exit path (uipc_syscalls.c:1677-1680), because kern_sendfile() only zeroes *sbytes after its early error gotos (:1734 vs :1699-1732). Demonstrated stable leak of a kernel virtual address (0xfffff80117c88a40) as unprivileged uid 1001 by seeding the stack slot with a preceding socket(2) call; also captured 0xffffffff809a5db0 on the first-call variant.",
  "exploit_chain": "unpriv sendfile(valid_file_fd, -1, 0, 0, NULL, &sbytes, 0) -> EBADF -> 8 bytes of stale kernel stack returned in *sbytes; repeatable, includes kernel pointers (KASLR defeat); single stack slot per call, value controllable only via preceding-syscall stack residue.",
  "evidence": [
    "run.log (root + unpriv runs; leak3.c stable KVA leak 0xfffff80117c88a40)",
    "poc_sendfile.c / leak3.c",
    "fix.diff + fix_run.log (patched kernel returns 0 on all paths)"
  ],
  "kernel_refs": [
    "sys/kern/uipc_syscalls.c:1594",
    "sys/kern/uipc_syscalls.c:1645-1648",
    "sys/kern/uipc_syscalls.c:1674-1681",
    "sys/kern/uipc_syscalls.c:1699-1734"
  ],
  "poc_changes": "Added a second program (leak3.c): the initial PoC's printf-per-sample re-dirtied the stack slot and masked the leak after the first call; seeding the slot with a preceding socket(2) immediately before sendfile makes the KVA leak stable across samples.",
  "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": 300,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -o poc_sendfile poc_sendfile.c && cc -O2 -o leak3 leak3.c",
  "run_cmd": "./poc_sendfile && ./leak3",
  "code_hash": "9d905ab439c8c9d6d8d04b173a70028f0c37bdb7c4f6a84923641d46dc65c144 (poc_sendfile.c); 3b97269848f74194db2bc9a54205bd6023e19ebfb90e1c91502d95f553eef176 (leak3.c)",
  "notes": "FreeBSD's counterpart initializes *sbytes early and copies out only on success; the unconditional copyout of an uninitialized local is DragonFly-specific. Impact limited to one 8-byte stack slot per call -> Medium.",
  "recommended_fix": "Initialize 'off_t sbytes = 0;' in sys_sendfile() (and ideally copy out only when kern_sendfile was reached)",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Sun Aug 30 23:56:25 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "One-line fix (off_t sbytes = 0). Patched kernel returns 0 in *sbytes on every early-error path; baseline stable KVA leak gone.",
  "fix_evidence": [
    "fix.diff",
    "fix_run.log",
    "run.log"
  ]
}