DF-3297 / verdict.json
{ "finding_id": "DF-3297", "status": "reproduced", "reproduced": 1, "impact": "leak", "confidence": "certain", "verdict": "DIOCGETSRCNODES (pf_ioctl.c:2884 bcopy of struct pf_src_node + 2902 copyout) discloses raw kernel heap pointers to userland: the RB_ENTRY links rbe_left/rbe_right/rbe_parent are copied verbatim; only the 4-byte rule.nr is sanitized (2886). Reproduced on the guest through an O_RDONLY /dev/pf fd (the ioctl is in the FREAD allow-list, pf_ioctl.c:1069): with >=2 source-tracking nodes per cpu tree, qwords such as 0xfffff8008bb64460 / 0xfffff8008bb645a0 / 0xfffff8011757d6e0 print at +0x00/+0x08/+0x10, stable across consecutive dumps. Same family as DF-0277/0278/0279 but a distinct, previously unreported ioctl. Stock exposure is root-only (/dev/pf 0600 root:wheel, pf_ioctl.c:3360); wherever devfs grants read access (monitoring) this is a kernel heap-address oracle / KASLR defeat for unprivileged readers. Low severity, information disclosure only.", "exploit_chain": "reader with /dev/pf O_RDONLY -> DIOCGETSRCNODES (psn_len two-step) -> userland buffer contains pf_src_node structs with verbatim rbe_* kernel heap pointers -> heap-layout oracle aiding any separate memory-corruption bug; no direct memory-safety impact.", "evidence": [ "leak_sample.txt: node dumps with 0xfffff8008bb64500 / 0xfffff8008bb64460 / 0xfffff8011757d6e0 at RB_ENTRY offsets, stable across two runs", "run.log: full reproduction sequence (O_RDONLY open annotated)", "VERDICT.md: offset map + the code-certain (not demonstrated) upper-half rule.ptr leak" ], "kernel_refs": [ "sys/net/pf/pf_ioctl.c:2884", "sys/net/pf/pf_ioctl.c:2886", "sys/net/pf/pf_ioctl.c:2902", "sys/net/pf/pf_ioctl.c:1069", "sys/net/pf/pf_ioctl.c:3360", "sys/net/pf/pf.c:582" ], "poc_changes": "Authored from scratch; needed <net/if.h> include for IFNAMSIZ and lo0 aliases (127.0.0.2-8) to force >=2 nodes per cpu tree - singleton trees have NULL links.", "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": 600, "guest_dirty": 0, "build_cmd": "cc -O2 -o leak_srcnodes leak_srcnodes.c && cc -O2 -o conn2 conn2.c", "run_cmd": "kldload pf.ko; pfctl -f srcnodes.conf; pfctl -e; ./conn2 127.0.0.{2..8}; ./leak_srcnodes", "code_hash": "3286352ce26384f8a13e01ef6bc2e526bbc98ccb79eb6d91892711d3c86c5361", "notes": "Fix (fix.diff: bzero entry links + kif + full rule union after the nr assignment) authored but not build-validated - non-corruption Low finding, validation reserved for memory-corruption class per contract.", "recommended_fix": "Zero pstore->entry, pstore->kif and pstore->rule.ptr (after re-assigning rule.nr) in DIOCGETSRCNODES before copyout, pf_ioctl.c:2884-2902." } |