DF-0744 / fix.diff
diff --git a/sys/netinet6/udp6_output.c b/sys/netinet6/udp6_output.c --- a/sys/netinet6/udp6_output.c +++ b/sys/netinet6/udp6_output.c @@ -261,7 +261,17 @@ releaseopt: if (control) { - ip6_clearpktopts(in6p->in6p_outputopts, -1); + /* + * DF-0744: clear the per-call local `opt`, never the user's + * sticky options. On the failure path of ip6_setpktoptions() + * we never reached line 138 (in6p->in6p_outputopts = &opt), + * so in6p->in6p_outputopts is STILL the sticky struct; + * clearing it destroys persistent setsockopt() state and + * leaks the local opt's per-call M_IP6OPT allocations. + * ip6_setpktoptions() always calls init_ip6pktopts(opt) + * first, so `opt` is always safe to clear here. + */ + ip6_clearpktopts(&opt, -1); in6p->in6p_outputopts = stickyopt; m_freem(control); } |