Date: Wed, 21 Sep 2005 21:17:20 GMT From: Pieter de Boer <pieter@thedarkside.nl> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/86429: if_tap doesn't filter frames not destined for itself Message-ID: <200509212117.j8LLHKUC069713@www.freebsd.org> Resent-Message-ID: <200509212120.j8LLK6aO077257@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 86429 >Category: kern >Synopsis: if_tap doesn't filter frames not destined for itself >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Sep 21 21:20:06 GMT 2005 >Closed-Date: >Last-Modified: >Originator: Pieter de Boer >Release: 6.0-BETA4 >Organization: >Environment: FreeBSD edinburgh 6.0-BETA4 FreeBSD 6.0-BETA4 #2: Sat Sep 17 18:01:08 CEST 2005 pieter@edinburgh:/usr/obj/usr/src/sys/kernel-31-07-2005 i386 >Description: The tap-driver doesn't filter incoming ethernet frames with a different unicast destination mac address than it's own mac address. The frames are sent up to the IP-stack, which may route them when forwarding is turned on. In my case leading to the system doing arp who-has on the destination IP-address in the ethernet frame, because the kernel wants to route the packet. On a virtual internet-exchange (www.virt-ix.net) using tap-tunnels this leads to a packet storm. >How-To-Repeat: Set up a ethernet tunnel using vtund/openvpn, configure two ethernet-addresses on both ends. On one system (A), turn on IP forwarding. On system B, create a static ARP entry for an address in the subnet, with a non-existent MAC address (like de:ad:ba:be:ca:fe). Run tcpdump on system B(!) and ping from system B to the IP address with the fake MAC address. See how system A does an arp request for the destination IP address because it wants to route it. This indicates the frame was wrongly pushed to the IP stack. >Fix: Adding an extra check to if_tap.c fixes this bug. The following patch works on my system. --- if_tap.c.orig Wed Sep 7 21:12:10 2005 +++ if_tap.c Thu Sep 8 22:05:46 2005 @@ -801,6 +801,7 @@ struct uio *uio; int flag; { + struct ether_header *eh; struct tap_softc *tp = dev->si_drv1; struct ifnet *ifp = tp->tap_ifp; struct mbuf *m; @@ -825,6 +826,21 @@ } m->m_pkthdr.rcvif = ifp; + + /* Check length first */ + if (m->m_len < sizeof(struct ether_header)) { + m_freem(m); + return(0); + } + + /* Only pass it up to the ether_input() layer if it's meant for us. */ + eh = mtod(m, struct ether_header *); + if (eh && (ifp->if_flags & IFF_PROMISC) == 0 && bcmp(eh->ether_dhost, + IFP2ENADDR(ifp), ETHER_ADDR_LEN) && + (eh->ether_dhost[0] & 1) == 0) { + m_freem(m); + return(0); + } /* Pass packet up to parent. */ (*ifp->if_input)(ifp, m); >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200509212117.j8LLHKUC069713>