DragonFlyBSD Kernel Audit
DF-0744 / fix.diff
← back to finding ↓ download raw
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);
 	}