DF-5803 / verdict.json
{ "finding_id": "DF-5803", "status": "reproduced", "reproduced": true, "impact": "leak", "confidence": "certain", "verdict": "expand_name() (sys/kern/kern_sig.c:2444-2516) kmallocs its output buffer without M_ZERO and NUL-terminates it only on the success path (2514); all three expansion-overflow branches log the buffer with %s before any terminator exists (2468/2481/2493), so kprintf walks uninitialized recycled heap past the initialized prefix and copies it into the kernel message buffer, which unprivileged users can read (sysctl kern.msgbuf, RC=0 verified). Reproduced deterministically on the guest with a same-bucket groom: a prior successful 1023-char expansion leaves its tail + NUL in the kmalloc bucket the overflowing trigger reuses, and the log line then contains bytes 1020.. of the previous allocation (e.g. 069 = tail of groomer pid 1069): pid 1072 (crashy), uid (0): Path `[1020xA]069crashy is too long. 3/3 batches. Precondition capping severity: reaching >MAXPATHLEN expansion requires a root-set kern.corefile (default %N.core cannot); trigger itself is an unprivileged abort().", "exploit_chain": "", "evidence": "run.log / run.2.log (LEAK_DETECTED lines with leaked bytes between prefix and comm), leak_full_line.txt (raw dmesg: [1020xA]069crashy), VERDICT.md mechanism + groom design, fix.diff (NUL-terminate temp[n] before each log(); git apply --check clean against sys/)", "kernel_refs": [ "sys/kern/kern_sig.c:2453", "sys/kern/kern_sig.c:2468", "sys/kern/kern_sig.c:2481", "sys/kern/kern_sig.c:2493", "sys/kern/kern_sig.c:2514", "sys/kern/kern_sig.c:2561" ], "poc_changes": "Seed sketch had no groom; the single-shot trigger usually hit a NUL at the prefix boundary, so a deterministic same-bucket groom was added (groomer.c + groom_rig.sh): size the previous successful expansion to exactly 1023 chars + NUL so the overflow branch provably prints offsets >=1020.", "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": 420, "guest_dirty": 0, "build_cmd": "cc -O -o /tmp/crashy /tmp/crashy.c && cc -O -o /tmp/groomer /tmp/groomer.c", "run_cmd": "sh /tmp/groom_rig.sh setup && sh /tmp/groom_rig.sh run 12 (root); dmesg | grep too long", "code_hash": "476ff7ce56b3d1766d57f1a7f7c9444ad2f91ede6f2dcef86cf9b0e04affc1f5", "notes": "Impact ceiling: small typical volume (bytes 1020..first-NUL; groom demonstrated 2-3 bytes/event) but structurally unbounded up to the kmalloc bucket contents. kern.msgbuf readable by unprivileged maxx (verified). Guest restored: kern.corefile back to %N.core, temp files removed, guest up. Findings 2 (gsignal dead-code pgfind leak) and 3 (kern_sigtimedwait token protocol) from this pass were not guest-tested (dead code / POSIX-race-only).", "recommended_fix": "NUL-terminate temp at temp[n] in each overflow branch before log() (see fix.diff); alternatively log only the configured format, not the partial expansion.", "fix_status": "not_testable", "fix_baseline_reproduced": true, "fix_patched_reproduced": false, "fix_verdict": "Fix not rebuilt: leak-class finding (not memory corruption, so rebuild not mandatory); the one-line NUL-termination fix is context-exact and git-apply --check clean against sys/kern/kern_sig.c; baseline bad behavior characterized in run.log/run.2.log/leak_full_line.txt.", "fix_evidence": "fix.diff; baseline evidence run.log, run.2.log, leak_full_line.txt" } |