DF-3199 / verdict.json
{ "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" ] } |