From: Alexander Bluhm Subject: missing kernel lock around ip6_mforward() To: tech@openbsd.org Date: Tue, 4 Aug 2026 20:38:25 +0200 Hi, When comparing ip_output() and ip6_output() I found a missing kernel lock around ip6_mforward(). It is not MP safe yet and locked elsewhere. To make future comparisons easier, sync the goto bad logic between ip6_output() and ip6_output(). ok? bluhm Index: netinet/ip_output.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_output.c,v diff -u -p -r1.419 ip_output.c --- netinet/ip_output.c 17 Jul 2026 18:51:29 -0000 1.419 +++ netinet/ip_output.c 4 Aug 2026 18:07:44 -0000 @@ -483,8 +483,11 @@ reroute: (error = if_output_ml(ifp, &ml, sintosa(dst), ro->ro_rt))) goto done; ipstat_inc(ips_fragmented); + goto done; -done: + bad: + m_freem(m); + done: if (ro == &iproute) rtfree(ro->ro_rt); if_put(ifp); @@ -492,10 +495,6 @@ done: tdb_unref(tdb); #endif /* IPSEC */ return (error); - -bad: - m_freem(m); - goto done; } #ifdef IPSEC Index: netinet6/ip6_output.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v diff -u -p -r1.306 ip6_output.c --- netinet6/ip6_output.c 25 Jun 2026 13:16:44 -0000 1.306 +++ netinet6/ip6_output.c 4 Aug 2026 18:07:42 -0000 @@ -492,10 +492,13 @@ reroute: if (atomic_load_int(&ip6_mforwarding) && ip6_mrouter[ifp->if_rdomain] && (flags & IPV6_FORWARDING) == 0) { - if (ip6_mforward(ip6, ifp, m, flags) != 0) { - m_freem(m); - goto done; - } + int rv; + + KERNEL_LOCK(); + rv = ip6_mforward(ip6, ifp, m, flags); + KERNEL_UNLOCK(); + if (rv != 0) + goto bad; } } #endif @@ -508,10 +511,8 @@ reroute: * destination group on the loopback interface. */ if (ip6->ip6_hlim == 0 || (ifp->if_flags & IFF_LOOPBACK) || - IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst)) { - m_freem(m); - goto done; - } + IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst)) + goto bad; } /* @@ -580,8 +581,7 @@ reroute: #if NPF > 0 if (pf_test(AF_INET6, PF_OUT, ifp, &m) != PF_PASS) { error = EACCES; - m_freem(m); - goto done; + goto bad; } if (m == NULL) goto done;