DragonFlyBSD Kernel Audit
DF-0742 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/netinet/ip_gre.c b/sys/netinet/ip_gre.c
--- a/sys/netinet/ip_gre.c
+++ b/sys/netinet/ip_gre.c
@@ -140,6 +140,18 @@
 		return (0);
 	}
 
+	/*
+	 * Ensure the GRE header overlay (struct greip = struct ip +
+	 * struct gre_h) is contiguous in the head mbuf before we
+	 * dereference gi_flags / gi_ptype at byte offset 20+.  ip_input
+	 * only guarantees m_len >= ip_hl*4; on chained mbufs (e.g. after
+	 * ip_reass m_cat) the GRE header may live in m_next, and the
+	 * overlay derefs would read stale mbuf-cluster residue (DF-0742).
+	 */
+	if ((m = m_pullup(m, sizeof(struct greip))) == NULL)
+		return (1);
+	gip = mtod(m, struct greip *);
+
 	IFNET_STAT_INC(&sc->sc_if, ipackets, 1);
 	IFNET_STAT_INC(&sc->sc_if, ibytes, m->m_pkthdr.len);
 
@@ -217,6 +229,23 @@
 		return(IPPROTO_DONE);
 	}
 
+	/*
+	 * Ensure the mobile header overlay (struct mobip_h = struct ip +
+	 * struct mobile_h) is contiguous in the head mbuf before we
+	 * dereference mh.proto / mh.osrc / mh.odst / gre_in_cksum at byte
+	 * offset 20+.  ip_input only guarantees m_len >= ip_hl*4; on
+	 * chained mbufs (e.g. after ip_reass m_cat) the mobile header may
+	 * live in m_next, and the overlay derefs would read stale
+	 * mbuf-cluster residue (DF-0742).
+	 */
+	if ((m = m_pullup(m, sizeof(struct mobip_h))) == NULL) {
+		*mp = NULL;
+		return (IPPROTO_DONE);
+	}
+	*mp = m;
+	ip = mtod(m, struct ip *);
+	mip = mtod(m, struct mobip_h *);
+
 	IFNET_STAT_INC(&sc->sc_if, ipackets, 1);
 	IFNET_STAT_INC(&sc->sc_if, ibytes, m->m_pkthdr.len);