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 */