diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2019-06-24 22:26:26 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2019-06-24 22:26:26 +0000 |
commit | 6fea75826081701a2b9e82e68e0642b68360acff (patch) | |
tree | 5b32c7dd83d996a12264da633c9f34e5aefc3992 | |
parent | d730ff1f811552cc4da4f8c6b7ca8a986ac0614b (diff) |
Since the recent recursion fix in rtable_walk(), deleting an interface
address could trigger the "rt->rt_ifidx == ifp->if_index" assertion.
In rtflushclone() the ifp that is passed to rtdeletemsg() has been
changed from the route interface to the ifa interface. Restore the
old behavior and get the route ifp.
found by regress/sys/netinet/carp; OK mpi@
-rw-r--r-- | sys/net/route.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/sys/net/route.c b/sys/net/route.c index b87a31ab789..2cc08bbe552 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -1,4 +1,4 @@ -/* $OpenBSD: route.c,v 1.386 2019/06/21 17:11:42 mpi Exp $ */ +/* $OpenBSD: route.c,v 1.387 2019/06/24 22:26:25 bluhm Exp $ */ /* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ /* @@ -156,7 +156,7 @@ void rt_timer_init(void); int rt_setgwroute(struct rtentry *, u_int); void rt_putgwroute(struct rtentry *); int rtflushclone1(struct rtentry *, void *, u_int); -int rtflushclone(struct ifnet *ifp, struct rtentry *, unsigned int); +int rtflushclone(struct rtentry *, unsigned int); int rt_ifa_purge_walker(struct rtentry *, void *, unsigned int); struct rtentry *rt_match(struct sockaddr *, uint32_t *, int, unsigned int); int rt_clone(struct rtentry **, struct sockaddr *, unsigned int); @@ -726,9 +726,10 @@ rtflushclone1(struct rtentry *rt, void *arg, u_int id) } int -rtflushclone(struct ifnet *ifp, struct rtentry *parent, unsigned int rtableid) +rtflushclone(struct rtentry *parent, unsigned int rtableid) { struct rtentry *rt = NULL; + struct ifnet *ifp; int error; #ifdef DIAGNOSTIC @@ -740,9 +741,15 @@ rtflushclone(struct ifnet *ifp, struct rtentry *parent, unsigned int rtableid) error = rtable_walk(rtableid, rt_key(parent)->sa_family, &rt, rtflushclone1, parent); if (rt != NULL && error == EEXIST) { - error = rtdeletemsg(rt, ifp, rtableid); - if (error == 0) + ifp = if_get(rt->rt_ifidx); + if (ifp == NULL) { error = EAGAIN; + } else { + error = rtdeletemsg(rt, ifp, rtableid); + if (error == 0) + error = EAGAIN; + if_put(ifp); + } } rtfree(rt); rt = NULL; @@ -791,7 +798,7 @@ rtrequest_delete(struct rt_addrinfo *info, u_int8_t prio, struct ifnet *ifp, /* Clean up any cloned children. */ if (ISSET(rt->rt_flags, RTF_CLONING)) - rtflushclone(ifp, rt, tableid); + rtflushclone(rt, tableid); rtfree(rt->rt_parent); rt->rt_parent = NULL; |