⬢ DragonFlyBSD Kernel Audit
DF-5709 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5709",
  "status": "reproduced",
  "verdict": "HEX_NCPYLEN(s) at sys/sys/libkern.h:67 expands its argument unparenthesized as (s * 3); a compound argument mis-sizes the callers buffer by C precedence (HEX_NCPYLEN(n+1) -> n+3 instead of 3n+3) while hexncpy writes 3 bytes per input byte at sep!=NULL (sys/libkern/hexncpy.c:56-61), so the next caller to size a buffer with a compound expression gets a linear heap/stack overflow. Demonstrated deterministically by a userland differential harness compiling the real kernel source: macro-sized array = 11 bytes vs 27 needed, hexncpy smashed 16 guard bytes past it and produced the full 26-char string. Latent today: all 13 in-tree call sites pass primary/parenthesized arguments (census in VERDICT.md), hence Info hardening with certain macro semantics. Same harness proves the pass-2 negative results: 60,800 guard-byte cases with 0 OOB writes on valid inputs, 48,640 differential cases with 0 unexplained output deviations (remaining deviations are exactly the known DF-2253 class plus cosmetic whole-group truncation), and reconfirms DF-2252 (outb[-1] NUL at inlen=0) and DF-2253 (sep==NULL eats final nibble) behave as documented.",
  "reproduced": true,
  "impact": "none",
  "confidence": "certain",
  "exploit_chain": "",
  "evidence": "findings/poc/DF-5709/run.log lines: T3 ... sizeof array = 11 (need 27), guard bytes smashed past the 11-byte buffer: 16 (true footprint = 27 bytes), T3 RESULT: LATENT OVERFLOW DEMONSTRATED; T1 guard theorem : cases=60800 violations=0; T2 differential ... dev_other=0; T4 DF-2252 confirmed; T4 DF-2253 confirmed. build.log compiles the guests /usr/src/sys/libkern/hexncpy.c (md5 09a38961bf3ecce78beed0079eacd651, byte-identical to the audited tree) unmodified via shim/sys/systm.h. Third run output md5 804494d763fb1715ec30e662a4c4e2a3 (deterministic).",
  "kernel_refs": [
    "sys/sys/libkern.h:67",
    "sys/libkern/hexncpy.c:42",
    "sys/libkern/hexncpy.c:56",
    "sys/libkern/hexncpy.c:62"
  ],
  "poc_changes": "No PoC seed existed (pass-2 new finding); authored the rig from scratch: hexdiff.c differential harness + shim/sys/systm.h (KKASSERT->assert, NULL, u_char) so sys/libkern/hexncpy.c compiles unmodified. First guest build failed on NULL-in-shim; fixed by adding <stddef.h> to the shim. Harness embeds HEX_NCPYLEN verbatim from sys/sys/libkern.h:67 plus the parenthesized HEX_NCPYLEN_FIXED fix variant.",
  "attempts": 2,
  "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": 180,
  "guest_dirty": 0,
  "build_cmd": "guest user maxx: cd /home/maxx/df5709 && HEXNCPY_SRC=/usr/src/sys/libkern/hexncpy.c sh build.sh",
  "run_cmd": "guest user maxx: cd /home/maxx/df5709 && sh run.sh",
  "code_hash": "d8c013f872d1337d4c0040f892134749cd903388101fd00958a8d5eadce351e4",
  "notes": "Info/latent: no in-tree caller misuses the macro today (13-site census in VERDICT.md). Pass-2 negative results proven by the same harness: (1) footprint theorem - no OOB write for any inlen>0/outlen>=3 (max touched index 3*floor(outlen/3)-1 <= outlen-1, 60800 guarded cases, 0 violations); (2) reference differential - 0 unexplained deviations, sep==NULL deviations are the known DF-2253 class, sep!=NULL deviations are cosmetic whole-group truncation granularity; (3) no hexnput/parse side exists in-tree; (4) sep==\"\" writes NUL separators (truncated-at-first-pair output) - no caller passes it, not filed; (5) KKASSERT-out variant folds into DF-2252s primitive; (6) s*3 int overflow unreachable (max live len 65535). Cross-ref for DF-0269 owners: new debug-gated trigger - if_spppsubr.c:3906 clamps len to attacker h->len AFTER the len<4 check (3902), so len-4=-2 wraps through u_short to 65534 at sppp_print_bytes (3927) -> VLA[65534] + outlen 196602, same sink as DF-0269.",
  "recommended_fix": "Parenthesize the macro argument: #define HEX_NCPYLEN(s) ((s) * 3) (sys/sys/libkern.h:67)",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "Kernel rebuild not warranted for an Info latent macro defect with no kernel manifestation; the one-line fix is validated inside the harness itself (HEX_NCPYLEN_FIXED variant sizes arrays/expansions correctly: 27, and its guard section stays intact). fix.diff authored against the read-only sys/ tree, never applied.",
  "fix_evidence": "run.log T3 section: HEX_NCPYLEN_FIXED(NBYTES+1) -> sizeof array = 27 vs macros 11; fix.diff = the same parenthesization for sys/sys/libkern.h:67."
}