diff options
author | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2000-01-11 08:26:46 +0000 |
---|---|---|
committer | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2000-01-11 08:26:46 +0000 |
commit | 074010f2d5d8bb362115f5c86431173104909d90 (patch) | |
tree | 7069439dbe8580bb4d9038b2817941531bbb7c89 /sys/net | |
parent | a853761906afe1426f60be8219e87cf8e5d0c85d (diff) |
Add a recursion depth limit, similar to if_gif.c; also, when
computing the route for the GRE tunnel, verify that it does not point
back to ourselves.
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if_gre.c | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c index 31f7d9b7280..f9750e28871 100644 --- a/sys/net/if_gre.c +++ b/sys/net/if_gre.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_gre.c,v 1.4 2000/01/08 01:39:24 angelos Exp $ */ +/* $OpenBSD: if_gre.c,v 1.5 2000/01/11 08:26:45 angelos Exp $ */ /* $NetBSD: if_gre.c,v 1.9 1999/10/25 19:18:11 drochner Exp $ */ /* @@ -89,6 +89,10 @@ #include <net/if_gre.h> +#ifndef GRE_RECURSION_LIMIT +#define GRE_RECURSION_LIMIT 3 /* How many levels of recursion allowed */ +#endif /* GRE_RECURSION_LIMIT */ + #define GREMTU 1450 /* XXX this is below the standard MTU of 1500 Bytes, allowing for headers, but we should possibly do path mtu discovery @@ -102,7 +106,7 @@ struct gre_softc gre_softc[NGRE]; /* * We can control the acceptance of GRE and MobileIP packets by * altering the sysctl net.inet.gre.allow and net.inet.mobileip.allow values - * respectively. Zero means drop them, all else is acceptance. + * respectively. Zero means drop them, all else is acceptance. */ int gre_allow = 0; int ip_mobile_allow = 0; @@ -159,6 +163,15 @@ gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, u_char ttl = 255; u_short etype = 0; struct mobile_h mob_h; + static int recursions = 0; /* XXX MUTEX */ + + /* Try to limit infinite recursion through misconfiguration */ + if (++recursions >= GRE_RECURSION_LIMIT) { + IF_DROP(&ifp->if_snd); + m_freem(m); + recursions = 0; + return (EIO); /* Use the same as in if_gif.c */ + } #if NBPFILTER >0 if (ifp->if_bpf) @@ -169,6 +182,7 @@ gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, if (ip_mobile_allow == 0) { IF_DROP(&ifp->if_snd); m_freem(m); + recursions = 0; return (EACCES); } @@ -185,6 +199,7 @@ gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, m = m_pullup(m, sizeof(struct ip)); if (m == 0) { IF_DROP(&ifp->if_snd); + recursions = 0; return (ENOBUFS); } else @@ -195,6 +210,7 @@ gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, sizeof(inp->ip_hl << 2)); if (m == 0) { IF_DROP(&ifp->if_snd); + recursions = 0; return (ENOBUFS); } } @@ -231,6 +247,7 @@ gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, if (m0 == NULL) { IF_DROP(&ifp->if_snd); m_freem(m); + recursions = 0; return (ENOBUFS); } @@ -261,12 +278,14 @@ gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, } else { /* AF_INET */ IF_DROP(&ifp->if_snd); m_freem(m); + recursions = 0; return (EINVAL); } } else if (sc->g_proto == IPPROTO_GRE) { if (gre_allow == 0) { IF_DROP(&ifp->if_snd); m_freem(m); + recursions = 0; return (EACCES); } @@ -276,6 +295,7 @@ gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, m = m_pullup(m, sizeof(struct ip)); if (m == 0) { IF_DROP(&ifp->if_snd); + recursions = 0; return (ENOBUFS); } } @@ -297,6 +317,7 @@ gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, default: IF_DROP(&ifp->if_snd); m_freem(m); + recursions = 0; return (EAFNOSUPPORT); } @@ -305,11 +326,13 @@ gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, error = EINVAL; IF_DROP(&ifp->if_snd); m_freem(m); + recursions = 0; return (error); } if (m == NULL) { IF_DROP(&ifp->if_snd); + recursions = 0; return (ENOBUFS); } @@ -338,6 +361,7 @@ gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, error = ip_output(m, NULL, &sc->route, 0, NULL, NULL); if (error) ifp->if_oerrors++; + recursions = 0; return (error); } @@ -377,6 +401,12 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } gre_compute_route(sc); + if (sc->route.ro_rt == 0) { + sc->g_src.s_addr = INADDR_ANY; + sc->g_dst.s_addr = INADDR_ANY; + return EIO; /* Is this is good ? */ + } + ifp->if_flags |= IFF_UP; } } @@ -461,6 +491,12 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } gre_compute_route(sc); + if (sc->route.ro_rt == 0) + { + sc->g_src.s_addr = INADDR_ANY; + sc->g_dst.s_addr = INADDR_ANY; + return EIO; /* Is this is good ? */ + } ifp->if_flags |= IFF_UP; } break; @@ -527,6 +563,17 @@ gre_compute_route(struct gre_softc *sc) return; /* + * Check whether we just created a loop. An even more paranoid + * check would be against all GRE interfaces, but that would + * not allow people to link GRE tunnels. + */ + if (ro->ro_rt->rt_ifp == &sc->sc_if) { + RTFREE(ro->ro_rt); + ro->ro_rt = (struct rtentry *) 0; + return; + } + + /* * now change it back - else ip_output will just drop * the route and search one to this interface ... */ |