⬢ DragonFlyBSD Kernel Audit
DF-2582 / verdict.json
← back to finding ↓ download raw
{
 "finding_id": "DF-2582",
 "status": "reproduced",
 "reproduced": 1,
 "impact": "corruption",
 "confidence": "certain",
 "verdict": "REPRODUCED as root on the stock guest (kldload ipfw3 + ipfw3_basic, firewall disabled during the test): APPEND accepts masklen 0, 33 and 64 (setsockopt rc=0 each). Behavioral proof in one table: empty table -> 1.2.3.4 not found; honest 10.1.2.0/24 -> 10.1.2.9 found / 10.9.9.9 not found; after appending 11.0.0.5/33 the entry is stored as 0.0.0.0/1, so 99.0.0.1 (top bit 0) now MATCHES the table while 200.1.1.1 does not - the bogus catch-all from the unbounded shift is live in the radix lookup tree the firewall datapath uses. Root-gated (raw socket).",
 "exploit_chain": "no escalation path: raw socket / ipfw3 config is root-gated (SYSCAP_NONET_RAW); wrong masks corrupt the firewall rule matching the admin configured",
 "evidence": "run.log: append masklen 0/33/64 all rc=0 (ACCEPTED); honest /24 -> 10.1.2.9 found, 10.9.9.9 not; after /33 append 99.0.0.1 FOUND while 200.1.1.1 NOT - the UB shift stored 0.0.0.0/1 live in the lookup tree",
 "kernel_refs": [
  "sys/net/ipfw3_basic/ip_fw3_table.c:161",
  "sys/net/ipfw3_basic/ip_fw3_table.c:164"
 ],
 "poc_changes": "Rebuilt the seed entirely: DFly ipfw3 sockopt convention is setsockopt/getsockopt optname IP_FW_X with an ip_fw_x_header opcode prefix; the SHOW readback is dead on this kernel (walks depend on a counter that append increments only on rnh_addaddr FAILURE), so the proof uses IP_FW_TABLE_TEST lookups with a fresh table id and clean negative controls.",
 "attempts": 6,
 "guest_uname": "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",
 "runtime_sec": 60,
 "guest_dirty": 0,
 "build_cmd": "cc -o ipfw3_masklen ipfw3_masklen.c",
 "run_cmd": "as root after kldload ipfw3 and kldload ipfw3_basic (net.inet.ip.fw3.enable=0 to keep ssh alive): ./ipfw3_masklen",
 "code_hash": "916e7740d8b339de8b4a5ec5e788d7af07683fa6a650e463561db93c3fabe166",
 "notes": "ADJACENT OBSERVATION (not this finding): kldunload ipfw3_basic after table creation panics in rn_flush (NULL radix head walked from the unload flush, current process Idle) - boot.log excerpt saved as ipfw3_unload_panic.txt; ip_fw3_ctl_table_show also depends on a counter that table_append_dispatch increments only on rnh_addaddr FAILURE (inverted), making SHOW always return count=0. ",
 "recommended_fix": "Validate mlen (reject >32, special-case 0 -> zero mask) before the shift.",
 "fix_status": "not_testable",
 "fix_kernel_uname": null,
 "fix_baseline_reproduced": null,
 "fix_patched_reproduced": null,
 "fix_verdict": "fix.diff compile-validated in the batch combined kernel build (all 37 diffs of this batch applied to in-guest /usr/src; make -j6 nativekernel KERNCONF=X86_64_GENERIC, see batch build log referenced in VERDICT.md); no behavior A/B performed for this Info-tier item; behavior A/B intentionally skipped for Info tier",
 "fix_evidence": "batch combined kernel build log (see findings/poc/_batch41 note in VERDICT.md)"
}