⬢ DragonFlyBSD Kernel Audit
DF-3425 / fix.diff
← back to finding ↓ download raw
--- a/sys/netinet/ip_encap.c
+++ b/sys/netinet/ip_encap.c
@@ -92,6 +92,13 @@
 #include <sys/thread2.h>
 MALLOC_DEFINE(M_IPENCAP, "IP Encapsulation", "IP Encapsulation");
 
+/*
+ * The encaptab walk in encap4_input()/encap6_input() runs from netisr
+ * transport processing, i.e. with mp_token held.  Mutators must take
+ * mp_token too so they cannot unlink+free an entry (or the caller's
+ * softc, via ep->arg) while a walk is in flight (DF-3425).
+ */
+
 static void encap_add (struct encaptab *);
 static int mask_match (const struct encaptab *, const struct sockaddr *,
 		const struct sockaddr *);
@@ -326,6 +333,7 @@
 {
 	struct encaptab *ep;
 
+	lwkt_gettoken(&mp_token);
 	crit_enter();
 	/* sanity check on args */
 	if (sp->sa_len > sizeof ep->src || dp->sa_len > sizeof ep->dst)
@@ -369,10 +377,12 @@
 	encap_add(ep);
 
 	crit_exit();
+	lwkt_reltoken(&mp_token);
 	return ep;
 
 fail:
 	crit_exit();
+	lwkt_reltoken(&mp_token);
 	return NULL;
 }
 
@@ -383,6 +393,7 @@
 {
 	struct encaptab *ep;
 
+	lwkt_gettoken(&mp_token);
 	crit_enter();
 	/* sanity check on args */
 	if (!func)
@@ -401,10 +412,12 @@
 	encap_add(ep);
 
 	crit_exit();
+	lwkt_reltoken(&mp_token);
 	return ep;
 
 fail:
 	crit_exit();
+	lwkt_reltoken(&mp_token);
 	return NULL;
 }
 
@@ -414,14 +427,17 @@
 	const struct encaptab *ep = cookie;
 	struct encaptab *p;
 
+	lwkt_gettoken(&mp_token);
 	for (p = LIST_FIRST(&encaptab); p; p = LIST_NEXT(p, chain)) {
 		if (p == ep) {
 			LIST_REMOVE(p, chain);
 			kfree(p, M_IPENCAP);	/*XXX*/
+			lwkt_reltoken(&mp_token);
 			return 0;
 		}
 	}
 
+	lwkt_reltoken(&mp_token);
 	return EINVAL;
 }