Subject: kern/21483: misconfigured gre may lead to unbound recursion
To: None <gnats-bugs@gnats.netbsd.org>
From: Martin Husemann <martin@aprisoft.de>
List: netbsd-bugs
Date: 05/06/2003 18:13:34
>Number:         21483
>Category:       kern
>Synopsis:       misconfigured gre may lead to unbound recursion
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue May 06 16:14:00 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator:     Martin Husemann
>Release:        NetBSD 1.6R
>Organization:
	
>Environment:
System: NetBSD beasty.aprisoft.de 1.6R NetBSD 1.6R (BEASTY) #0: Tue Apr 29 17:15:27 CEST 2003 martin@beasty.aprisoft.de:/usr/src/sys/arch/i386/compile/BEASTY i386
Architecture: i386
Machine: i386
>Description:

sys/net/if_gre.c tries to avoid sending packets through the tunnel, when 
gre_compute_route failed (i.e. the far end of the tunnel is not reachable
outside the tunnel itself). It sets IFF_RUNNING if the route is available
and clears it otherwise.

I think in gre_output the test for IFF_UP + IFF_RUNNING is slightly wrong,
so packets pass if only IFF_UP is set. This leads to recursive routing
and kernel stack overflows.

>How-To-Repeat:

Code review.

>Fix:

Besides the above fix, I'd suggest adding some diagnostic output when failing
to find a route. This is unrelated, but included in the following patch
anyway.

Index: if_gre.c
===================================================================
RCS file: /cvsroot/src/sys/net/if_gre.c,v
retrieving revision 1.44
diff -u -r1.44 if_gre.c
--- if_gre.c	2003/02/23 04:28:10	1.44
+++ if_gre.c	2003/05/06 16:07:57
@@ -191,7 +191,7 @@
 	u_short etype = 0;
 	struct mobile_h mob_h;
 
-	if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == 0 ||
+	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING) ||
 	    sc->g_src.s_addr == INADDR_ANY || sc->g_dst.s_addr == INADDR_ANY) {
 		m_freem(m);
 		error = ENETDOWN;
@@ -441,8 +441,11 @@
 				RTFREE(sc->route.ro_rt);
 			if (gre_compute_route(sc) == 0)
 				ifp->if_flags |= IFF_RUNNING;
-			else
+			else {
 				ifp->if_flags &= ~IFF_RUNNING;
+				printf("%s: configuration problem, no tunnel "
+				    "route found\n", ifp->if_xname);
+			}
 		}
 		break;
 	case GREGADDRS:

>Release-Note:
>Audit-Trail:
>Unformatted: