Author: bz Date: Mon Nov 18 21:59:47 2019 New Revision: 354832 URL: https://svnweb.freebsd.org/changeset/base/354832
Log: icmpv6: Fix mbuf change in mld After r354748 mld_input() can change the mbuf. The new pointer is never returned to icmp6_input() and when passed to icmp6_rip6_input() the mbuf may no longer valid leading to a panic. Pass a pointer to the mbuf to mld_input() so we can return an updated version in the non-error case. Add a test sending an MLD packet case which will trigger this bug. Pointyhat to: bz Reported by: gallatin, thj MFC After: 2 weeks X-MFC with: r354748 Sponsored by: Netflix Added: head/tests/sys/netinet6/mld.py (contents, props changed) head/tests/sys/netinet6/mld.sh (contents, props changed) Modified: head/sys/netinet6/icmp6.c head/sys/netinet6/mld6.c head/sys/netinet6/mld6_var.h head/tests/sys/netinet6/Makefile Modified: head/sys/netinet6/icmp6.c ============================================================================== --- head/sys/netinet6/icmp6.c Mon Nov 18 21:54:29 2019 (r354831) +++ head/sys/netinet6/icmp6.c Mon Nov 18 21:59:47 2019 (r354832) @@ -604,7 +604,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) */ if ((ip6->ip6_hlim != 1) || (m->m_flags & M_RTALERT_MLD) == 0) goto freeit; - if (mld_input(m, off, icmp6len) != 0) { + if (mld_input(&m, off, icmp6len) != 0) { *mp = NULL; return (IPPROTO_DONE); } Modified: head/sys/netinet6/mld6.c ============================================================================== --- head/sys/netinet6/mld6.c Mon Nov 18 21:54:29 2019 (r354831) +++ head/sys/netinet6/mld6.c Mon Nov 18 21:59:47 2019 (r354832) @@ -1249,13 +1249,15 @@ out_locked: * Return IPPROTO_DONE if we freed m. Otherwise, return 0. */ int -mld_input(struct mbuf *m, int off, int icmp6len) +mld_input(struct mbuf **mp, int off, int icmp6len) { struct ifnet *ifp; struct ip6_hdr *ip6; + struct mbuf *m; struct mld_hdr *mld; int mldlen; + m = *mp; CTR3(KTR_MLD, "%s: called w/mbuf (%p,%d)", __func__, m, off); ifp = m->m_pkthdr.rcvif; @@ -1278,6 +1280,7 @@ mld_input(struct mbuf *m, int off, int icmp6len) ICMP6STAT_INC(icp6s_badlen); return (IPPROTO_DONE); } + *mp = m; ip6 = mtod(m, struct ip6_hdr *); mld = (struct mld_hdr *)(mtod(m, uint8_t *) + off); Modified: head/sys/netinet6/mld6_var.h ============================================================================== --- head/sys/netinet6/mld6_var.h Mon Nov 18 21:54:29 2019 (r354831) +++ head/sys/netinet6/mld6_var.h Mon Nov 18 21:59:47 2019 (r354832) @@ -167,7 +167,7 @@ struct mld_ifsoftc * void mld_domifdetach(struct ifnet *); void mld_fasttimo(void); void mld_ifdetach(struct ifnet *, struct in6_multi_head *); -int mld_input(struct mbuf *, int, int); +int mld_input(struct mbuf **, int, int); void mld_slowtimo(void); #ifdef SYSCTL_DECL Modified: head/tests/sys/netinet6/Makefile ============================================================================== --- head/tests/sys/netinet6/Makefile Mon Nov 18 21:54:29 2019 (r354831) +++ head/tests/sys/netinet6/Makefile Mon Nov 18 21:59:47 2019 (r354832) @@ -7,12 +7,15 @@ FILESDIR= ${TESTSDIR} ATF_TESTS_SH= \ exthdr \ + mld \ scapyi386 ${PACKAGE}FILES+= exthdr.py +${PACKAGE}FILES+= mld.py ${PACKAGE}FILES+= scapyi386.py ${PACKAGE}FILESMODE_exthdr.py= 0555 +${PACKAGE}FILESMODE_mld.py= 0555 ${PACKAGE}FILESMODE_scapyi386.py=0555 TESTS_SUBDIRS+= frag6 Added: head/tests/sys/netinet6/mld.py ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tests/sys/netinet6/mld.py Mon Nov 18 21:59:47 2019 (r354832) @@ -0,0 +1,76 @@ +#!/usr/bin/env python +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Netflix, Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +import argparse +import scapy.all as sp +import socket +import sys +import binascii + +def main(): + parser = argparse.ArgumentParser("scapyi386.py", + description="IPv6 Ethernet Dest MAC test") + parser.add_argument('--sendif', nargs=1, + required=True, + help='The interface through which the packet will be sent') + parser.add_argument('--recvif', nargs=1, + required=True, + help='The interface on which to check for the packet') + parser.add_argument('--src', nargs=1, + required=True, + help='The source IP address') + parser.add_argument('--to', nargs=1, + required=True, + help='The destination IP address') + parser.add_argument('--debug', + required=False, action='store_true', + help='Enable test debugging') + parser.add_argument('--mldraw01', + required=False, action='store_true', + help='Multicast Listener Query Raw01') + + args = parser.parse_args() + + pkt = None + if args.mldraw01: + pkt = sp.Ether() / \ + sp.IPv6(dst="ff02::1", hlim=1, nh=0) / \ + sp.IPv6ExtHdrHopByHop(options = sp.RouterAlert(value=0)) / \ + sp.ICMPv6MLQuery() + if pkt is None: + sys.exit(1) + if args.debug: + pkt.display() + sp.sendp(pkt, iface=args.sendif[0], verbose=False) + + sys.exit(0) + +if __name__ == '__main__': + main() Added: head/tests/sys/netinet6/mld.sh ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tests/sys/netinet6/mld.sh Mon Nov 18 21:59:47 2019 (r354832) @@ -0,0 +1,89 @@ +# $FreeBSD$ +#- +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Netflix, Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +. $(atf_get_srcdir)/../common/vnet.subr + +atf_test_case "mldraw01" "cleanup" +mldraw01_head() { + + atf_set descr 'Test for correct Ethernet Destination MAC address' + atf_set require.user root + atf_set require.progs scapy +} + +mldraw01_body() { + + ids=65533 + id=`printf "%x" ${ids}` + if [ $$ -gt 65535 ]; then + xl=`printf "%x" $(($$ - 65535))` + yl="1" + else + xl=`printf "%x" $$` + yl="" + fi + + vnet_init + + ip6a="2001:db8:6666:0000:${yl}:${id}:1:${xl}" + ip6b="2001:db8:6666:0000:${yl}:${id}:2:${xl}" + + epair=$(vnet_mkepair) + ifconfig ${epair}a up + ifconfig ${epair}a inet6 ${ip6a}/64 + + jname="v6t-${id}-${yl}-${xl}" + vnet_mkjail ${jname} ${epair}b + jexec ${jname} ifconfig ${epair}b up + jexec ${jname} ifconfig ${epair}b inet6 ${ip6b}/64 + + # Let IPv6 ND do its thing. + #ping6 -q -c 1 ff02::1%${epair}a + #ping6 -q -c 1 ${ip6b} + sleep 3 + + pyname=$(atf_get ident) + + atf_check -s exit:0 $(atf_get_srcdir)/mld.py \ + --sendif ${epair}a --recvif ${epair}a \ + --src ${ip6a} --to ${ip6b} \ + --${pyname} +} + +mldraw01_cleanup() { + + vnet_cleanup +} + +atf_init_test_cases() +{ + + atf_add_test_case "mldraw01" +} + +# end _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"