DragonFlyBSD Kernel Audit
DF-0720 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/netgraph7/ng_sppp.c b/sys/netgraph7/ng_sppp.c
--- a/sys/netgraph7/ng_sppp.c
+++ b/sys/netgraph7/ng_sppp.c
@@ -33,7 +33,7 @@
 #include <net/if.h>
 #include <net/if_types.h>
 #include <net/bpf.h>
-#include <net/if_sppp.h>
+#include <net/sppp/if_sppp.h>
 
 #include <netinet/in.h>
 
@@ -42,6 +42,13 @@
 #include "ng_parse.h"
 #include "ng_sppp.h"
 
+/* DF-0720: DragonFly's struct sppp (net/sppp/if_sppp.h) nests the ifnet as
+ * pp_arpcom.ac_if, so IFP2SP must offset back to the enclosing struct sppp.
+ * (These macros were undefined, which is why this file did not compile.) */
+#define IFP2SP(ifp)	\
+    ((struct sppp *)((char *)(ifp) - offsetof(struct sppp, pp_arpcom.ac_if)))
+#define SP2IFP(sp)	(&(sp)->pp_arpcom.ac_if)
+
 #ifdef NG_SEPARATE_MALLOC
 MALLOC_DEFINE(M_NETGRAPH_SPPP, "netgraph_sppp", "netgraph sppp node ");
 #else
@@ -246,12 +253,17 @@
 	if (priv == NULL)
 		return (ENOMEM);
 
-	ifp = if_alloc(IFT_PPP);
-	if (ifp == NULL) {
+	/* DF-0720: sppp_attach()/IFP2SP treat ifp as the pp_arpcom.ac_if member
+	 * of a struct sppp and write ~1KB of PPP state past the ifnet.  Allocate
+	 * a full struct sppp here (NOT if_alloc(IFT_PPP), which only returns
+	 * sizeof(struct ifnet) and would be overflowed by sppp_attach). */
+	pp = kmalloc(sizeof(struct sppp), M_NETGRAPH_SPPP, M_WAITOK | M_ZERO);
+	if (pp == NULL) {
 		kfree(priv, M_NETGRAPH_SPPP);
 		return (ENOSPC);
 	}
-	pp = IFP2SP(ifp);
+	ifp = SP2IFP(pp);
+	ifp->if_type = IFT_PPP;
 
 	/* Link them together */
 	ifp->if_softc = priv;
@@ -393,7 +405,10 @@
 	bpfdetach (priv->ifp);
 	sppp_detach (priv->ifp);
 	if_detach (priv->ifp);
-	if_free(priv->ifp);
+	/* DF-0720: free the struct sppp we allocated (of which ifp is a member). */
+	if (priv->ifp->if_description != NULL)
+		kfree(priv->ifp->if_description, M_IFDESCR);
+	kfree(IFP2SP(priv->ifp), M_NETGRAPH_SPPP);
 	ng_sppp_free_unit (priv->unit);
 	kfree(priv, M_NETGRAPH_SPPP);
 	NG_NODE_SET_PRIVATE (node, NULL);