DragonFlyBSD Kernel Audit
DF-2684 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-2684",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "leak",
  "confidence": "certain",
  "verdict": "sysctl kern.file (CTL_KERN/KERN_FILE) is world-readable: sysctl_root() gates only writes, and sysctl_kern_file_callback (kern_descrip.c:3453-3503) filters by prison only. kcore_make_file (subr_kcore.c:58-77) copies ufile->f_file = kfile and ufile->f_data = kfile->f_data -- raw kernel heap pointers -- into every exported kinfo_file. Unprivileged uid 1001 read 136 entries: 136 carried non-NULL kernel pointers (struct file and vnode/socket addresses) and 120 belonged to other uids including root's fd types/flags/offsets (off=112 on root's password-file read). Pointer disclosure aids KASLR defeat and heap grooming for memory-corruption exploits; cross-uid fd-offset disclosure is an information leak across uid boundaries. Validated fix masks f_file/f_data for uid!=0: post-fix unprivileged read shows 0 pointers while root still sees 143 -- baseline-vs-patched deterministic.",
  "exploit_chain": "unprivileged sysctl(3) {CTL_KERN, KERN_FILE} -> kernel-heap addresses of every struct file and its vnode/socket + other users' fd offsets; the addresses are direct-map slab pointers usable to defeat KASLR and to aim UAF-reclaim grooming (e.g. for DF-2682-class bugs) -- no further chain needed for the leak itself.",
  "evidence": [
    "run.log: 'entries with kernel pointers: 136 / entries belonging to OTHER uids: 120 / RESULT: LEAK CONFIRMED' as uid 1001",
    "leak_sample.txt: pointer values across runs (0xfffff8xxxxxxxxxx direct-map slab addresses)",
    "run_fixed.log: post-fix 'entries with kernel pointers: 0' as uid 1001 and '143' as root",
    "VERDICT.md: root cause, why sysctl(8) hides it (opaque type), fix validation narrative"
  ],
  "kernel_refs": [
    "sys/kern/kern_descrip.c:3490",
    "sys/kern/kern_descrip.c:3453",
    "sys/kern/kern_descrip.c:3464",
    "sys/kern/subr_kcore.c:58",
    "sys/kern/kern_sysctl.c:1427"
  ],
  "poc_changes": "Direct sysctl(3) consumer written from scratch (userland sysctl(8) discards CTLTYPE_OPAQUE output, so the seed idea of shelling out to sysctl(8) showed nothing).",
  "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": 90,
  "guest_dirty": 0,
  "build_cmd": "cc -O -o kfile_leak kfile_leak.c",
  "run_cmd": "./kfile_leak",
  "code_hash": "c421798533927eb911be78a96cef827e284b9cda8e1a90f60bc77a679b98ffcc",
  "notes": "Fix validated on the patched guest kernel: unprivileged readers get f_file=0x0/f_data=0x0, root unchanged. fix_status=fixed, fix_baseline_reproduced=1, fix_patched_reproduced=0 (leak gone). Upstream may additionally want p_cansee-style row filtering for the cross-uid offset disclosure. Guest reset with-src afterwards.",
  "recommended_fix": "Mask kinfo_file.f_file/f_data for unprivileged readers in sysctl_kern_file_callback (validated fix.diff); consider p_cansee()-based row filtering for cross-user fd state."
}