⬢ DragonFlyBSD Kernel Audit
DF-3457 / fix.diff
← back to finding ↓ download raw
--- a/sys/net/gif/if_gif.c
+++ b/sys/net/gif/if_gif.c
@@ -178,6 +178,22 @@
 	struct gif_softc *sc = ifp->if_softc;
 	int err;
 
+	/*
+	 * Take the gif's ifnet serializer before tearing the softc state
+	 * down.  gif_output() holds this serializer (via
+	 * ifsq_serialize_hw(), which is ifp->if_serializer, if.c:642) for
+	 * the WHOLE encapsulation including the gif_psrc re-read at the
+	 * AF dispatch, and the SIOCSIFPHYADDR/SIOCDIFPHYADDR ioctl paths
+	 * already run under ifnet_serialize_all() (if.c:2350-2352).
+	 * Without this, `ifconfig gifN destroy` racing in-flight traffic
+	 * frees/NULLs gif_psrc & gif_pdst between gif_output_serialized()'s
+	 * NULL guard (if_gif.c:345-350) and its deref at :373 (and
+	 * between in_gif_output()'s pointer load at in_gif.c:101-102 and
+	 * its last use), panicking the kernel (DF-3457).
+	 *
+	 * Nothing below takes ifp's serializer, so there is no recursion.
+	 */
+	ifnet_serialize_all(ifp);
 	gif_delete_tunnel(&sc->gif_if);
 	LIST_REMOVE(sc, gif_list);
 #ifdef INET6
@@ -193,6 +209,7 @@
 	}
 #endif
 	gif_clear_cache(sc);
+	ifnet_deserialize_all(ifp);
 
 	bpfdetach(ifp);
 	if_detach(ifp);