Module Name: src Committed By: maxv Date: Tue Feb 13 07:51:24 UTC 2018
Modified Files: src/sys/netinet: if_arp.c Log Message: Fix three things in arpintr(): * mtod can't return NULL. * It is wrong to kick the packet if m->m_len < arplen. While this check always returns false for native Ethernet interfaces, it may not if the frame is encapsulated in EtherIP/L2TP. Use m_pullup instead. * Remove XXX, it is fine. Reduce the indentation level afterwards. To generate a diff of this commit: cvs rdiff -u -r1.257 -r1.258 src/sys/netinet/if_arp.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/netinet/if_arp.c diff -u src/sys/netinet/if_arp.c:1.257 src/sys/netinet/if_arp.c:1.258 --- src/sys/netinet/if_arp.c:1.257 Tue Feb 13 07:44:25 2018 +++ src/sys/netinet/if_arp.c Tue Feb 13 07:51:24 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_arp.c,v 1.257 2018/02/13 07:44:25 maxv Exp $ */ +/* $NetBSD: if_arp.c,v 1.258 2018/02/13 07:51:24 maxv Exp $ */ /* * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc. @@ -68,7 +68,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.257 2018/02/13 07:44:25 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.258 2018/02/13 07:51:24 maxv Exp $"); #ifdef _KERNEL_OPT #include "opt_ddb.h" @@ -939,12 +939,10 @@ arpintr(void) MCLAIM(m, &arpdomain.dom_mowner); ARP_STATINC(ARP_STAT_RCVTOTAL); - /* - * First, make sure we have at least struct arphdr. - */ - if (m->m_len < sizeof(struct arphdr) || - (ar = mtod(m, struct arphdr *)) == NULL) + arplen = sizeof(struct arphdr); + if (m->m_len < arplen && (m = m_pullup(m, arplen)) == NULL) goto badlen; + ar = mtod(m, struct arphdr *); rcvif = m_get_rcvif(m, &s); if (__predict_false(rcvif == NULL)) { @@ -963,23 +961,26 @@ arpintr(void) } m_put_rcvif(rcvif, &s); - if (/* XXX ntohs(ar->ar_hrd) == ARPHRD_ETHER && */ - m->m_len >= arplen) - switch (ntohs(ar->ar_pro)) { - case ETHERTYPE_IP: - case ETHERTYPE_IPTRAILERS: - in_arpinput(m); - continue; - default: - ARP_STATINC(ARP_STAT_RCVBADPROTO); - } - else { -badlen: - ARP_STATINC(ARP_STAT_RCVBADLEN); + if (m->m_len < arplen && (m = m_pullup(m, arplen)) == NULL) + goto badlen; + ar = mtod(m, struct arphdr *); + + switch (ntohs(ar->ar_pro)) { + case ETHERTYPE_IP: + case ETHERTYPE_IPTRAILERS: + in_arpinput(m); + continue; + default: + ARP_STATINC(ARP_STAT_RCVBADPROTO); + goto free; } + +badlen: + ARP_STATINC(ARP_STAT_RCVBADLEN); free: m_freem(m); } + out: SOFTNET_KERNEL_UNLOCK_UNLESS_NET_MPSAFE(); return; /* XXX gcc */