O_VIA/O_RECV/O_XMIT name[IFNAMSIZ] not required NUL-terminated: kfnmatch() pattern scan runs past the 16-byte field toward/past the rule allocation
Summary
iface_match() matches interface names with kfnmatch(cmd->name, if_xname, 0) when cmd->p.glob is set. Validation only enforces the instruction length (6 words) - name[] is the trailing 16 bytes of ipfw_insn_if and is never checked for NUL termination, and the glob flag is raw user data. With all 16 name bytes non-NUL, kfnmatch walks the pattern byte-by-byte into the following instructions and, if the remainder of the rule contains no zero byte, past RULESIZE into adjacent heap (sequential OOB read until a zero). The strncmp path is properly bounded. Root-installed rule + any matching packet; only observable as a match/no-match oracle on adjacent bytes - negligible confidentiality, bounds-discipline defect. Fix: require memchr(cmd->name, 0, IFNAMSIZ) at install. [VERIFIED pass2: install-gap demonstrated live with non-NUL name rule accepted then never matching; kfnmatch rangematch walk reachable but oracle-only; fix compile-validated]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3262 Β· 9 files| File | Type | Description | Size | |
|---|---|---|---|---|
| run.log | β | 724 B | view raw | |
| README.md | β | 586 B | β raw | |
| VERDICT.md | β | 2.2 KB | β raw | |
| build.sh | β | 162 B | view raw | |
| run.sh | β | 158 B | view raw | |
| manifest.json | β | 670 B | view raw | |
| verdict.json | β | 1.9 KB | view raw | |
| fix.diff | β | 635 B | view raw | |
| env.txt | β | 272 B | view raw |
DF-3262 -- verification pack
Finding: O_VIA/O_RECV/O_XMIT name[] not required NUL-terminated; kfnmatch walks past rule
Status: not_reproduced / impact leak / confidence likely
What was run
guest: addset via 2000 <16-byte-name> (same tool as DF-3261)
How to reproduce
guest: addset via 2000 vtnet0[AAAAAAAAA; ipfw -S list; traffic; ipfw show 2000
Expected
rule installs with no NUL in name[] (validation gap); never matches the control pattern
See VERDICT.md for the full narrative and verdict.json for the persisted machine verdict. Artifacts: run.log.
DF-3262 verification
Kernel: DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64
Bottom line
The validation gap is demonstrated live: an O_VIA glob rule whose 16-byte name has no NUL byte installs through IP_FW_ADD (only the instruction length is checked at ip_fw2.c:5482) and shows in ipfw -S list, while a properly terminated control rule matches traffic. Rigorous source analysis of libkern fnmatch shows the out-of-bounds pattern read is genuinely reachable but oracle-only: the default, ? and leading-* branches consume pattern in lockstep with the string (bounded by if_xname, <= 15 chars + NUL), but an unterminated [ opens rangematch()s bracket scan, which walks pattern bytes until a ] or an EOS byte - past the 16-byte name, through the rest of the rule, into adjacent heap when no zero byte intervenes. The result is a match/no-match oracle on adjacent kernel heap bytes with no crash or disclosure path; classification is therefore not_reproduced for want of an observable manifestation, with the gap and the reachability analysis on record.
Kernel references
Exploit chain
(none: availability/correctness finding; no privilege chain)
Fix
require memchr(name, 0, IFNAMSIZ) at install for O_RECV/O_XMIT/O_VIA
See fix.diff in this directory (git-apply-able against the read-only sys/ tree; applied only inside the disposable verification guest).
Reproduction
build: guest: addset via 2000 <16-byte-name> (same tool as DF-3261)
run: guest: addset via 2000 vtnet0[AAAAAAAAA; ipfw -S list; traffic; ipfw show 2000
expected: rule installs with no NUL in name[] (validation gap); never matches the control pattern
Notes on the PoC (what changed vs the finding sketch)
(none)
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
not_testableConfirmed kernel references
Detail
Evidence (decisive lines)
run.log (non-NUL rule installed and listed, zero matches vs NUL-terminated control matching), VERDICT.md fnmatch branch analysis
Verified recommended fix
require memchr(name, 0, IFNAMSIZ) at install for O_RECV/O_XMIT/O_VIA
Verdict
The validation gap is demonstrated live: an O_VIA glob rule whose 16-byte name has no NUL byte installs through IP_FW_ADD (only the instruction length is checked at ip_fw2.c:5482) and shows in ipfw -S list, while a properly terminated control rule matches traffic. Rigorous source analysis of libkern fnmatch shows the out-of-bounds pattern read is genuinely reachable but oracle-only: the default, ? and leading-* branches consume pattern in lockstep with the string (bounded by if_xname, <= 15 chars + NUL), but an unterminated [ opens rangematch()s bracket scan, which walks pattern bytes until a ] or an EOS byte - past the 16-byte name, through the rest of the rule, into adjacent heap when no zero byte intervenes. The result is a match/no-match oracle on adjacent kernel heap bytes with no crash or disclosure path; classification is therefore not_reproduced for want of an observable manifestation, with the gap and the reachability analysis on record.
No comments yet.