DragonFlyBSD Kernel Audit
DF-0414 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/netgraph/pppoe/ng_pppoe.c b/sys/netgraph/pppoe/ng_pppoe.c
--- a/sys/netgraph/pppoe/ng_pppoe.c
+++ b/sys/netgraph/pppoe/ng_pppoe.c
@@ -967,6 +967,24 @@
 				LEAVE(EMSGSIZE);
 			}
 
+			/*
+			 * Sanity-check the PPPoE payload length field against
+			 * the actual mbuf size.  get_tag()/scan_tags() use
+			 * ph->length as the walk bound (next_tag() at line ~275
+			 * computes end = &ph->tag[0] + ph->length), so an
+			 * attacker-controlled ph->length that exceeds the real
+			 * payload drives those walkers into an out-of-bounds
+			 * kernel heap read.  The session branch already
+			 * performs the equivalent check after m_adj(); the
+			 * discovery branch omitted it.  Drop the frame if the
+			 * claimed length does not fit in the mbuf we have.
+			 * (m_pullup above guarantees m_pkthdr.len >= sizeof(*wh).)
+			 */
+			if (m->m_pkthdr.len - sizeof(*wh) < length) {
+				kprintf("pppoe: discovery ph->length too large\n");
+				LEAVE(EMSGSIZE);
+			}
+
 			switch(code) {
 			case	PADI_CODE:
 				/*