summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authormpi <mpi@openbsd.org>2019-06-21 17:11:42 +0000
committermpi <mpi@openbsd.org>2019-06-21 17:11:42 +0000
commitcf34c7c30780cd8ede039358a15c5494afd24684 (patch)
tree8ca2049c1943ac2434008d1dd0fec0adf9fce650 /sys/netinet6
parenttweak wording a bit. always talk about creating a new environment. (diff)
downloadwireguard-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.c8
-rw-r--r--sys/netinet6/nd6.h4
-rw-r--r--sys/netinet6/nd6_rtr.c49
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);
}