Subject: Packets hitting interfaces not marked as UP
To: None <tech-net@NetBSD.ORG>
From: Martin Husemann <martin@duskware.de>
List: tech-net
Date: 11/24/2001 00:52:51
Accidently I found an easy way to crash a NetBSD machine (seems 1.5.2 and 
-current behave the same, besides the "create" call):

 - make sure you have no default route
 - ifconfig gre0 create
 - ifconfig gre0 192.168.177.2 192.168.177.4 down
 - ping 192.168.177.4

What happens? You now have an gre0 device with no tunnel configured. Such
an interface can not work - it should block all packets anyway.

Furthermore, this interface is down, so it should block all packets.

But in reality, ip_ouput calls 

  error = (*ifp->if_output)(ifp, m, sintosa(dst), ro->ro_rt);

(line 620 of ip_output.c in -current), which is gre_output, which in turn
ends up calling 

  error = ip_output(m, NULL, &sc->route, 0, NULL);

(line 333 of if_gre.c in -current).

Ok, there we are, infinite recursion, kernel stack overflow, depending on
architecture you end up with an instant reboot (the debugger won't catch it)
or a RED state exception and drop back into firmware - or whatever.

There are two problems I have with this:

 (a) why is the interface output routine called at all - the interface
     is not IFF_UP. I see all random ethernet interface drivers test
     this explicitly, why is the test not done in ip_output?

 (b) should if_gre.c get a flag in it's softc noting whether a tunnel
     route has been successfully found and drop packets otherwise?
     Or is there an easy way to detect the recursion from the route
     stored in sc->route?

Martin