diff options
author | mpi <mpi@openbsd.org> | 2019-06-21 17:11:42 +0000 |
---|---|---|
committer | mpi <mpi@openbsd.org> | 2019-06-21 17:11:42 +0000 |
commit | cf34c7c30780cd8ede039358a15c5494afd24684 (patch) | |
tree | 8ca2049c1943ac2434008d1dd0fec0adf9fce650 /sys/netinet6 | |
parent | tweak wording a bit. always talk about creating a new environment. (diff) | |
download | wireguard-openbsd-cf34c7c30780cd8ede039358a15c5494afd24684.tar.xz wireguard-openbsd-cf34c7c30780cd8ede039358a15c5494afd24684.zip |
Prevent recursions by not deleting entries inside rtable_walk(9).
rtable_walk(9) now passes a routing entry back to the caller when
a non zero value is returned and if it asked for it.
This allows us to call rtdeletemsg()/rtrequest_delete() from the
caller without creating a recursion because of rtflushclone().
Multicast code hasn't been adapted and is still possibly creating
recursions. However multicast route entries aren't cloned so if
a recursion exists it isn't because of rtflushclone().
Fix stack exhaustion triggered by the use of "-msave-args".
Issue reported by Dániel Lévai on bugs@ confirmed by and ok bluhm@.
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/ip6_mroute.c | 8 | ||||
-rw-r--r-- | sys/netinet6/nd6.h | 4 | ||||
-rw-r--r-- | sys/netinet6/nd6_rtr.c | 49 |
3 files changed, 36 insertions, 25 deletions
diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c index 512353701b8..4188f58506b 100644 --- a/sys/netinet6/ip6_mroute.c +++ b/sys/netinet6/ip6_mroute.c @@ -454,8 +454,10 @@ mrt6_sysctl_mfc(void *oldp, size_t *oldlenp) msa.ms6a_len = *oldlenp; msa.ms6a_needed = 0; - for (rtableid = 0; rtableid <= RT_TABLEID_MAX; rtableid++) - rtable_walk(rtableid, AF_INET6, mrt6_rtwalk_mf6csysctl, &msa); + for (rtableid = 0; rtableid <= RT_TABLEID_MAX; rtableid++) { + rtable_walk(rtableid, AF_INET6, NULL, mrt6_rtwalk_mf6csysctl, + &msa); + } if (msa.ms6a_minfos != NULL && msa.ms6a_needed > 0 && (error = copyout(msa.ms6a_minfos, oldp, msa.ms6a_needed)) != 0) { @@ -523,7 +525,7 @@ ip6_mrouter_done(struct socket *so) NET_ASSERT_LOCKED(); /* Delete all remaining installed multicast routes. */ - rtable_walk(rtableid, AF_INET6, mrouter6_rtwalk_delete, NULL); + rtable_walk(rtableid, AF_INET6, NULL, mrouter6_rtwalk_delete, NULL); /* Unregister all interfaces in the domain. */ TAILQ_FOREACH(ifp, &ifnet, if_list) { diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h index 8a7a0f39ca1..4449a7ed73c 100644 --- a/sys/netinet6/nd6.h +++ b/sys/netinet6/nd6.h @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6.h,v 1.74 2017/11/27 15:41:30 mpi Exp $ */ +/* $OpenBSD: nd6.h,v 1.75 2019/06/21 17:11:43 mpi Exp $ */ /* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */ /* @@ -193,7 +193,7 @@ void nd6_dad_stop(struct ifaddr *); void nd6_rtr_cache(struct mbuf *, int, int, int); int in6_ifdel(struct ifnet *, struct in6_addr *); -void rt6_flush(struct in6_addr *, struct ifnet *); +int rt6_flush(struct in6_addr *, struct ifnet *); void nd6_expire_timer_update(struct in6_ifaddr *); #endif /* _KERNEL */ diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index fac53728b97..87adb7ce73f 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6_rtr.c,v 1.166 2018/01/23 22:06:42 bluhm Exp $ */ +/* $OpenBSD: nd6_rtr.c,v 1.167 2019/06/21 17:11:43 mpi Exp $ */ /* $KAME: nd6_rtr.c,v 1.97 2001/02/07 11:09:13 itojun Exp $ */ /* @@ -173,28 +173,48 @@ nd6_rtr_cache(struct mbuf *m, int off, int icmp6len, int icmp6_type) * it shouldn't be called when acting as a router. * The gateway must already contain KAME's hack for link-local scope. */ -void +int rt6_flush(struct in6_addr *gateway, struct ifnet *ifp) { + struct rt_addrinfo info; + struct sockaddr_in6 sa_mask; + struct rtentry *rt = NULL; + int error; + NET_ASSERT_LOCKED(); /* We'll care only link-local addresses */ if (!IN6_IS_ADDR_LINKLOCAL(gateway)) - return; + return (0); KASSERT(gateway->s6_addr16[1] != 0); - rtable_walk(ifp->if_rdomain, AF_INET6, rt6_deleteroute, gateway); + do { + error = rtable_walk(ifp->if_rdomain, AF_INET6, &rt, + rt6_deleteroute, gateway); + if (rt != NULL && error == EEXIST) { + memset(&info, 0, sizeof(info)); + info.rti_flags = rt->rt_flags; + info.rti_info[RTAX_DST] = rt_key(rt); + info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; + info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, + &sa_mask); + error = rtrequest_delete(&info, RTP_ANY, ifp, NULL, + ifp->if_rdomain); + if (error == 0) + error = EAGAIN; + } + rtfree(rt); + rt = NULL; + } while (error == EAGAIN); + + return (error); } int rt6_deleteroute(struct rtentry *rt, void *arg, unsigned int id) { - struct ifnet *ifp; - struct rt_addrinfo info; struct in6_addr *gate = (struct in6_addr *)arg; - struct sockaddr_in6 sa_mask; - int error = 0; if (rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_INET6) return (0); @@ -217,16 +237,5 @@ rt6_deleteroute(struct rtentry *rt, void *arg, unsigned int id) if ((rt->rt_flags & RTF_HOST) == 0) return (0); - ifp = if_get(rt->rt_ifidx); - if (ifp != NULL) { - bzero(&info, sizeof(info)); - info.rti_flags = rt->rt_flags; - info.rti_info[RTAX_DST] = rt_key(rt); - info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; - info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, &sa_mask); - error = rtrequest_delete(&info, RTP_ANY, ifp, NULL, id); - } - if_put(ifp); - - return (error != 0 ? error : EAGAIN); + return (EEXIST); } |