Index | Thread | Search

From:
Alexander Bluhm <bluhm@openbsd.org>
Subject:
missing kernel lock around ip6_mforward()
To:
tech@openbsd.org
Date:
Tue, 4 Aug 2026 20:38:25 +0200

Download raw body.

Thread
  • Alexander Bluhm:

    missing kernel lock around ip6_mforward()

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;