Module Name:    src
Committed By:   maxv
Date:           Mon Jan 15 13:14:18 UTC 2018

Modified Files:
        src/sys/net: if_ethersubr.c

Log Message:
Fix two bugs in altq_etherclassify. When scanning the mbuf chain we need
to make sure that m_next is not NULL, otherwise NULL deref. After that,
we must not touch m->m_pkthdr, given that 'm' may not be the first mbuf
of the chain anymore.

Declare mtop, and add a KASSERT to make sure it has M_PKTHDR set.


To generate a diff of this commit:
cvs rdiff -u -r1.254 -r1.255 src/sys/net/if_ethersubr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/net/if_ethersubr.c
diff -u src/sys/net/if_ethersubr.c:1.254 src/sys/net/if_ethersubr.c:1.255
--- src/sys/net/if_ethersubr.c:1.254	Mon Jan 15 12:17:05 2018
+++ src/sys/net/if_ethersubr.c	Mon Jan 15 13:14:18 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_ethersubr.c,v 1.254 2018/01/15 12:17:05 maxv Exp $	*/
+/*	$NetBSD: if_ethersubr.c,v 1.255 2018/01/15 13:14:18 maxv Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.254 2018/01/15 12:17:05 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.255 2018/01/15 13:14:18 maxv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -463,10 +463,13 @@ void
 altq_etherclassify(struct ifaltq *ifq, struct mbuf *m)
 {
 	struct ether_header *eh;
+	struct mbuf *mtop = m;
 	uint16_t ether_type;
 	int hlen, af, hdrsize;
 	void *hdr;
 
+	KASSERT((mtop->m_flags & M_PKTHDR) != 0);
+
 	hlen = ETHER_HDR_LEN;
 	eh = mtod(m, struct ether_header *);
 
@@ -508,7 +511,10 @@ altq_etherclassify(struct ifaltq *ifq, s
 	while (m->m_len <= hlen) {
 		hlen -= m->m_len;
 		m = m->m_next;
+		if (m == NULL)
+			goto bad;
 	}
+
 	if (m->m_len < (hlen + hdrsize)) {
 		/*
 		 * protocol header not in a single mbuf.
@@ -527,11 +533,12 @@ altq_etherclassify(struct ifaltq *ifq, s
 
 	hdr = mtod(m, void *);
 
-	if (ALTQ_NEEDS_CLASSIFY(ifq))
-		m->m_pkthdr.pattr_class =
+	if (ALTQ_NEEDS_CLASSIFY(ifq)) {
+		mtop->m_pkthdr.pattr_class =
 		    (*ifq->altq_classify)(ifq->altq_clfier, m, af);
-	m->m_pkthdr.pattr_af = af;
-	m->m_pkthdr.pattr_hdr = hdr;
+	}
+	mtop->m_pkthdr.pattr_af = af;
+	mtop->m_pkthdr.pattr_hdr = hdr;
 
 	m->m_data -= hlen;
 	m->m_len += hlen;
@@ -539,9 +546,9 @@ altq_etherclassify(struct ifaltq *ifq, s
 	return;
 
 bad:
-	m->m_pkthdr.pattr_class = NULL;
-	m->m_pkthdr.pattr_hdr = NULL;
-	m->m_pkthdr.pattr_af = AF_UNSPEC;
+	mtop->m_pkthdr.pattr_class = NULL;
+	mtop->m_pkthdr.pattr_hdr = NULL;
+	mtop->m_pkthdr.pattr_af = AF_UNSPEC;
 }
 #endif /* ALTQ */
 

Reply via email to