DF-3483 / verdict.json
{ "finding_id": "DF-3483", "status": "reproduced", "reproduced": 1, "impact": "dos", "confidence": "certain", "verdict": "ng_generic_msg()s NGM_MKPEER/NGM_CONNECT/NGM_NAME/NGM_RMHOOK arglen-mismatch error paths return EINVAL without kfree(msg) (ng_base.c:1263, 1279, 1296, 1309), violating the handler-frees-message contract (ng_base.c:1177); neither caller frees on error (ng_send_msg:1226, ngintr:2062), so every failing generic control message permanently leaks its user-sized struct ng_mesg allocation. Root-gated like netgraph7s DF-3474 (control socket is SYSCAP_RESTRICTEDROOT, ng_socket.c:172): v1 has no NG_FREE_ITEM/item abstraction to share DF-3474s mark-only semantics (its queue entries are really freed), but this is the same family -- control-message leak on generic error paths. Reproduced with exact size correlation: 50k bad MKPEER sends leaked 1935/1861 free pages vs 1953 predicted (160B zone), 50k bad NAME sends leaked 1122/1154 vs 1172 predicted (96B zone), while the addressing-failure control phase was flat (104/-1 pages). 200k total bad sends leaked ~30MB permanently. Impact ceiling: unbounded kernel heap exhaustion by a root caller (kldload/fork/socket degradation) -- local DoS, no info leak, no corruption. Fix validated: kfree(msg) added at all four sites; patched netgraph.ko shows 11/1 and 0/0 page deltas (noise) on the same test.", "exploit_chain": "root (or compromised root daemon) -> 4-arglen-off-by-one control message on an AF_NETGRAPH control socket -> ng_generic_msg early-returns without freeing -> each send permanently leaks kmalloc(payload) -> unbounded kernel heap exhaustion (DoS). No uid=0 route: leak-only.", "evidence": [ "findings/poc/DF-3483/run.log \u2014 baseline: good 104p / bad 1935p / bad2 1122p per 50k", "findings/poc/DF-3483/run.2.log \u2014 repeat baseline: good -1p / bad 1861p / bad2 1154p", "findings/poc/DF-3483/fix_run.log \u2014 patched netgraph.ko: bad 11p/1p, bad2 0p/0p \u2014 leak gone", "findings/poc/DF-3483/arglenleak.c \u2014 A/B/C trigger with free-page accounting", "findings/poc/DF-3483/fix.diff \u2014 4x kfree(msg) before the early returns" ], "kernel_refs": [ "sys/netgraph/netgraph/ng_base.c:1263", "sys/netgraph/netgraph/ng_base.c:1279", "sys/netgraph/netgraph/ng_base.c:1296", "sys/netgraph/netgraph/ng_base.c:1309", "sys/netgraph/netgraph/ng_base.c:1177", "sys/netgraph/netgraph/ng_base.c:1218", "sys/netgraph/netgraph/ng_base.c:1669", "sys/netgraph/socket/ng_socket.c:172", "sys/netgraph/socket/ng_socket.c:253" ], "poc_changes": "none of substance; wrote the A/B/C trigger from scratch (no seed PoC). Measured via vm.stats.vm.v_free_count deltas after vmstat -m proved unreliable for module malloc types on this guest (same caveat as DF-3474).", "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": 1800, "guest_dirty": 0, "build_cmd": "cc -O2 -w -o arglenleak arglenleak.c", "run_cmd": "kldload ng_socket; ./arglenleak 50000", "code_hash": "e08b9edb1ccc88d05ecd84e8026d5cbd3786d277bec650af0598c7182d29826a", "notes": "Baseline runs on stock /boot/kernel modules; fix validation on in-guest-rebuilt netgraph.ko (patch applied to the guests /usr/src copy; never applied to the audit tree). Guest reset with-src afterwards. The same early-return-without-free pattern should be audited in every node types rcvmsg across sys/netgraph/ (out of this files scope).", "recommended_fix": "kfree(msg, M_NETGRAPH) before each of the four arglen-mismatch returns in ng_generic_msg() \u2014 see fix.diff.", "fix_status": "fixed", "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: (netgraph.ko rebuilt in-guest with fix.diff, loaded on fresh boot; ng_socket/ng_ppp/ng_ksocket stock)", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "Same 3-phase A/B/C test on the patched module: bad 11/1 pages, bad2 0/0 pages (noise) vs baseline 1935/1861 and 1122/1154 \u2014 leak eliminated, good path unchanged.", "fix_evidence": "findings/poc/DF-3483/fix_run.log" } |