Race condition in ip6_getpmtu (actually gif)?

Craig Boston craig at olyun.gank.org
Thu Jan 26 18:10:49 PST 2006


On Thu, Jan 26, 2006 at 08:05:28PM -0600, Craig Boston wrote:
> Attached is a quick hack...

Whoops, patch _actually_ attached this time.
-------------- next part --------------
=== net/if_gif.c
==================================================================
--- net/if_gif.c	(/vendor/sys)	(revision 292)
+++ net/if_gif.c	(/gif6)	(revision 292)
@@ -154,6 +154,8 @@
 		return (ENOSPC);
 	}
 
+	mtx_init(&sc->gif_ro_mtx, "gif_ro_mtx", NULL, MTX_DEF);
+
 	GIF2IFP(sc)->if_softc = sc;
 	if_initname(GIF2IFP(sc), ifc->ifc_name, unit);
 
@@ -227,6 +229,7 @@
 	mtx_lock(&gif_mtx);
 	LIST_REMOVE(sc, gif_list);
 	mtx_unlock(&gif_mtx);
+	mtx_destroy(&sc->gif_ro_mtx);
 	gif_destroy(sc);
 }
 
=== net/if_gif.h
==================================================================
--- net/if_gif.h	(/vendor/sys)	(revision 292)
+++ net/if_gif.h	(/gif6)	(revision 292)
@@ -65,6 +65,7 @@
 		struct route_in6 gifscr_ro6; /* xxx */
 #endif
 	} gifsc_gifscr;
+	struct mtx	gif_ro_mtx;
 	int		gif_flags;
 	const struct encaptab *encap_cookie4;
 	const struct encaptab *encap_cookie6;
=== netinet6/in6_gif.c
==================================================================
--- netinet6/in6_gif.c	(/vendor/sys)	(revision 292)
+++ netinet6/in6_gif.c	(/gif6)	(revision 292)
@@ -195,25 +195,30 @@
 		dst->sin6_family = sin6_dst->sin6_family;
 		dst->sin6_len = sizeof(struct sockaddr_in6);
 		dst->sin6_addr = sin6_dst->sin6_addr;
+		mtx_lock(&sc->gif_ro_mtx);
 		if (sc->gif_ro6.ro_rt) {
 			RTFREE(sc->gif_ro6.ro_rt);
 			sc->gif_ro6.ro_rt = NULL;
 		}
+		mtx_unlock(&sc->gif_ro_mtx);
 #if 0
 		GIF2IFP(sc)->if_mtu = GIF_MTU;
 #endif
 	}
 
+	mtx_lock(&sc->gif_ro_mtx);
 	if (sc->gif_ro6.ro_rt == NULL) {
 		rtalloc((struct route *)&sc->gif_ro6);
 		if (sc->gif_ro6.ro_rt == NULL) {
 			m_freem(m);
+			mtx_unlock(&sc->gif_ro_mtx);
 			return ENETUNREACH;
 		}
 
 		/* if it constitutes infinite encapsulation, punt. */
 		if (sc->gif_ro.ro_rt->rt_ifp == ifp) {
 			m_freem(m);
+			mtx_unlock(&sc->gif_ro_mtx);
 			return ENETUNREACH;	/*XXX*/
 		}
 #if 0
@@ -238,6 +243,7 @@
 		RTFREE(sc->gif_ro6.ro_rt);
 		sc->gif_ro6.ro_rt = NULL;
 	}
+	mtx_unlock(&sc->gif_ro_mtx);
 
 	return (error);
 }


More information about the freebsd-net mailing list