⬢ DragonFlyBSD Kernel Audit
DF-3199 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3199",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "leak",
  "confidence": "certain",
  "verdict": "devfs_rule_create_link() strips strlen(pattern)-1 bytes from the NODE name when the pattern ends in *; leading *s make patterns of any length match short names, so the read starts up to ~200 bytes past the nodes exact-size kmallocd d_name and copies adjacent M_DEVFS heap contents into the alias name, world-readable in /dev. Reproduced 3/3 deterministic: LK17.urandom / LK20.ndom (same adjacent chunk, shifted) / LK33.kpmap - stale device-name strings from neighbouring 16-byte-zone chunks; unprivileged user maxx listed the leaked alias live.",
  "exploit_chain": "privileged rule install -> every matching short-named node gets an alias whose name embeds heap bytes past d_name -> any user reads them via readdir/lookup on /dev",
  "evidence": [
    "run.log / leak_sample.txt: LK17.urandom, LK20.ndom, LK33.kpmap identical across 3 runs",
    "unprivileged ls showing LIVE17urandom",
    "run.fixed.log: aliases plain (strip clamped), no leaked bytes"
  ],
  "kernel_refs": [
    "sys/vfs/devfs/devfs_rules.c:243",
    "sys/vfs/devfs/devfs_rules.c:247",
    "sys/vfs/devfs/devfs_core.c:253"
  ],
  "poc_changes": "offsets 100/200 removed: their ~95-star patterns crash earlier via DF-3202; added path-scoped linkname (lk/) so aliases cannot self-match (DF-3201)",
  "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": 45,
  "guest_dirty": 1,
  "build_cmd": "cc -static -O -o leak_linkname leak_linkname.c",
  "run_cmd": "./leak_linkname",
  "code_hash": "d316c1ad30e7509ade30e16d5175bd83fc039c266da6e72e4e5f8692aa3b72ff",
  "notes": "leaked content is bounded by the first NUL (stale strings in the small-name zone); the over-read offset itself is attacker-chosen (17..1022). Combined with DF-3201-class self-match patterns the same primitive also drives unbounded alias generation.",
  "recommended_fix": "clamp the strip to the node name length: if (len > node->d_dir.d_namlen) len = node->d_dir.d_namlen;",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Tue Sep  8 10:25:07 UTC 2026  root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "post-fix aliases carry no leaked suffix (LK17..LK33 plain); offsets with >32 stars are rejected at ADD by the DF-3202 cap",
  "fix_evidence": [
    "DF-3199/run.fixed.log"
  ]
}