DF-3360 / verdict.json
{ "finding_id": "DF-3360", "status": "not_reproduced", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "The OOB access is real, remotely triggerable, and compiled into the shipped pf.ko (objdump: movzwl 0x2(%r15)/mov %ax,0x2(%r15) with %r15==opts+38 possible and no guard), and 300,000 crafted malformed-MSS packets demonstrably executed the path (scrub rule evaluations climbed, guest stable). However, on this gcc80 -O2 INVARIANTS build opts[40..41] is an 8-byte alignment-padding slot at rbp-0x30 (no live local or saved register adjacent), so the 2-byte read/write cannot corrupt live state on the shipped binary. Defect: certain (disassembly + source proof). Runtime manifestation: none on this build; impact becomes live if a different compiler/-O level/KASAN-style layout places data at opts+40. Secondary oracle: th->th_sum is fixupd with stale-stack bytes and copied back, a 2-byte stale-stack oracle in transit packets.", "exploit_chain": "", "evidence": [ "findings/poc/DF-3360/pf_normalize_tcpopt.dis (shipped pf.ko disassembly; opts at rbp-0x58, access at opts+40)", "findings/poc/DF-3360/disassembly-analysis.txt (frame layout proof)", "findings/poc/DF-3360/mss_oob.c (trigger: SYN, th_off=15, [38xNOP][0x02 0x02])", "rule evaluation counters 416k+ after 100k packets with scrub max-mss 64; 200k more with max-mss 1; guest stable both runs" ], "kernel_refs": [ "sys/net/pf/pf_norm.c:1915", "sys/net/pf/pf_norm.c:1938-1946", "sys/netinet/tcp.h:148-149" ], "poc_changes": "Rewrote the seed-style sketch into a standalone raw-socket injector: fixed DFly-specific bits (ip_len must be in network order for raw IP, source must be a locally assigned address or sendto returns EADDRNOTAVAIL, pseudo-header checksum built manually for C89 declarations), options tile = 38xNOP + [TCPOPT_MAXSEG, len=2].", "attempts": 3, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 x86_64 (X86_64_GENERIC, INVARIANTS)", "runtime_sec": 240, "guest_dirty": 0, "build_cmd": "cc -O2 -o mss_oob mss_oob.c", "run_cmd": "pfctl -f mss.conf && pfctl -e && /root/poc/mss_oob 100000", "code_hash": "32b843a5b1352721ae1388f876ee0d85450e709345096b1279e18c34af133a7f", "notes": "scrub max-mss rule is a precondition (non-default config, common in practice). No uid0 path: this is a 2-byte stack OOB write whose value is rule-derived (htons(max_mss)) and whose position is fixed; on the shipped build it lands in padding. Recommended fix is a one-line optlen check.", "recommended_fix": "In pf_normalize_tcpopt() TCPOPT_MAXSEG case: if (optlen != TCPOLEN_MAXSEG) break;" } |