Module Name: src Committed By: knakahara Date: Fri Dec 4 02:26:12 UTC 2015
Modified Files: src/sys/net: if_gif.c Log Message: gif(4): Infinite recursion calls prevention code works again now. The prevention code haven't worked since gif(4) was changed to use softint(9). To work this prevention, git_output uses m_tag(9) like FreeBSD and OpenBSD. I tested with following code. ==================== # ifconfig gif0 create # ifconfig gif0 tunnel 10.1.1.1 10.1.1.2 # ifconfig gif0 inet 192.168.100.1 192.168.100.100 # ifconfig gif1 create # ifconfig gif1 tunnel 192.168.100.1 192.168.100.100 # ifconfig gif1 inet 192.168.101.1 192.168.101.101 # ifconfig gif2 create # ifconfig gif2 tunnel 192.168.101.1 192.168.101.101 # ifconfig gif2 inet 192.168.102.1 192.168.102.102 # ping -w 1 -c 1 192.168.102.102 # dmesg | tail -n 1 gif0: recursively called too many times(2) ==================== To generate a diff of this commit: cvs rdiff -u -r1.94 -r1.95 src/sys/net/if_gif.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_gif.c diff -u src/sys/net/if_gif.c:1.94 src/sys/net/if_gif.c:1.95 --- src/sys/net/if_gif.c:1.94 Thu Dec 3 03:03:58 2015 +++ src/sys/net/if_gif.c Fri Dec 4 02:26:11 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: if_gif.c,v 1.94 2015/12/03 03:03:58 knakahara Exp $ */ +/* $NetBSD: if_gif.c,v 1.95 2015/12/04 02:26:11 knakahara Exp $ */ /* $KAME: if_gif.c,v 1.76 2001/08/20 02:01:02 kjc Exp $ */ /* @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.94 2015/12/03 03:03:58 knakahara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.95 2015/12/04 02:26:11 knakahara Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -94,6 +94,7 @@ LIST_HEAD(, gif_softc) gif_softc_list; / static int gif_clone_create(struct if_clone *, int); static int gif_clone_destroy(struct ifnet *); +static int gif_check_nesting(struct ifnet *, struct mbuf *); static struct if_clone gif_cloner = IF_CLONE_INITIALIZER("gif", gif_clone_create, gif_clone_destroy); @@ -233,31 +234,56 @@ gif_encapcheck(struct mbuf *m, int off, } #endif +/* + * gif may cause infinite recursion calls when misconfigured. + * We'll prevent this by introducing upper limit. + */ +static int +gif_check_nesting(struct ifnet *ifp, struct mbuf *m) +{ + struct m_tag *mtag; + int *count; + + mtag = m_tag_find(m, PACKET_TAG_TUNNEL_INFO, NULL); + if (mtag != NULL) { + count = (int *)(mtag + 1); + if (++(*count) > max_gif_nesting) { + log(LOG_NOTICE, + "%s: recursively called too many times(%d)\n", + if_name(ifp), + *count); + return EIO; + } + } else { + mtag = m_tag_get(PACKET_TAG_TUNNEL_INFO, sizeof(*count), + M_NOWAIT); + if (mtag != NULL) { + m_tag_prepend(m, mtag); + count = (int *)(mtag + 1); + *count = 0; + } else { + log(LOG_DEBUG, + "%s: m_tag_get() failed, recursion calls are not prevented.\n", + if_name(ifp)); + } + } + + return 0; +} + int gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct rtentry *rt) { struct gif_softc *sc = ifp->if_softc; int error = 0; - static int called = 0; /* XXX: MUTEX */ ALTQ_DECL(struct altq_pktattr pktattr;) int s; IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr); - /* - * gif may cause infinite recursion calls when misconfigured. - * We'll prevent this by introducing upper limit. - * XXX: this mechanism may introduce another problem about - * mutual exclusion of the variable CALLED, especially if we - * use kernel thread. - */ - if (++called > max_gif_nesting) { - log(LOG_NOTICE, - "gif_output: recursively called too many times(%d)\n", - called); - m_freem(m); - error = EIO; /* is there better errno? */ + if ((error = gif_check_nesting(ifp, m)) != 0) { + m_free(m); goto end; } @@ -295,7 +321,6 @@ gif_output(struct ifnet *ifp, struct mbu error = 0; end: - called = 0; /* reset recursion counter */ if (error) ifp->if_oerrors++; return error;