DragonFlyBSD Kernel Audit
DF-0689 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/netinet/ip_encap.c b/sys/netinet/ip_encap.c
--- a/sys/netinet/ip_encap.c	2026-06-29 12:51:19.000000000 +0000
+++ b/sys/netinet/ip_encap.c	2026-07-19 07:47:01.904237148 +0000
@@ -90,8 +90,12 @@
 #include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/thread2.h>
+#include <sys/token.h>
 MALLOC_DEFINE(M_IPENCAP, "IP Encapsulation", "IP Encapsulation");
 
+/* DF-0689: serialize encaptab mutation vs. encap{4,6}_input walks. */
+static struct lwkt_token encaptab_token = LWKT_TOKEN_INITIALIZER(encaptab_token);
+
 static void encap_add (struct encaptab *);
 static int mask_match (const struct encaptab *, const struct sockaddr *,
 		const struct sockaddr *);
@@ -171,6 +175,7 @@
 
 	match = NULL;
 	matchprio = 0;
+	lwkt_gettoken(&encaptab_token);
 	for (ep = LIST_FIRST(&encaptab); ep; ep = LIST_NEXT(ep, chain)) {
 		if (ep->af != AF_INET)
 			continue;
@@ -224,8 +229,10 @@
 		} else {
 			m_freem(m);
 		}
+		lwkt_reltoken(&encaptab_token);
 		return(IPPROTO_DONE);
 	}
+	lwkt_reltoken(&encaptab_token);
 
 	/* for backward compatibility */
 	if (proto == IPPROTO_IPV4 && ipip_input) {
@@ -265,6 +272,7 @@
 
 	match = NULL;
 	matchprio = 0;
+	lwkt_gettoken(&encaptab_token);
 	for (ep = LIST_FIRST(&encaptab); ep; ep = LIST_NEXT(ep, chain)) {
 		if (ep->af != AF_INET6)
 			continue;
@@ -291,16 +299,20 @@
 	}
 
 	if (match) {
+		int rc;
 		/* found a match */
 		psw = match->psw;
 		if (psw && psw->pr_input) {
 			encap_fillarg(m, match);
-			return (*psw->pr_input)(mp, offp, proto);
+			rc = (*psw->pr_input)(mp, offp, proto);
 		} else {
 			m_freem(m);
-			return IPPROTO_DONE;
+			rc = IPPROTO_DONE;
 		}
+		lwkt_reltoken(&encaptab_token);
+		return rc;
 	}
+	lwkt_reltoken(&encaptab_token);
 
 	/* last resort: inject to raw socket */
 	return rip6_input(mp, offp, proto);
@@ -326,7 +338,7 @@
 {
 	struct encaptab *ep;
 
-	crit_enter();
+	lwkt_gettoken(&encaptab_token);
 	/* sanity check on args */
 	if (sp->sa_len > sizeof ep->src || dp->sa_len > sizeof ep->dst)
 		goto fail;
@@ -368,11 +380,11 @@
 
 	encap_add(ep);
 
-	crit_exit();
+	lwkt_reltoken(&encaptab_token);
 	return ep;
 
 fail:
-	crit_exit();
+	lwkt_reltoken(&encaptab_token);
 	return NULL;
 }
 
@@ -383,7 +395,7 @@
 {
 	struct encaptab *ep;
 
-	crit_enter();
+	lwkt_gettoken(&encaptab_token);
 	/* sanity check on args */
 	if (!func)
 		goto fail;
@@ -400,11 +412,11 @@
 
 	encap_add(ep);
 
-	crit_exit();
+	lwkt_reltoken(&encaptab_token);
 	return ep;
 
 fail:
-	crit_exit();
+	lwkt_reltoken(&encaptab_token);
 	return NULL;
 }