diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2019-06-21 17:11:44 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2019-06-21 17:11:44 +0000 |
commit | fb482f64f911b7fca87d82ac917a331783e5915c (patch) | |
tree | 5de16192a2d5c2016a8f06548095348d71e6ebdf /sys/net/rtable.c | |
parent | d54cd84095c832ef5111a5e80e44ec90ec860873 (diff) |
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/net/rtable.c')
-rw-r--r-- | sys/net/rtable.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/sys/net/rtable.c b/sys/net/rtable.c index 092d53b265f..ec57747f447 100644 --- a/sys/net/rtable.c +++ b/sys/net/rtable.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtable.c,v 1.68 2019/03/05 19:07:56 anton Exp $ */ +/* $OpenBSD: rtable.c,v 1.69 2019/06/21 17:11:42 mpi Exp $ */ /* * Copyright (c) 2014-2016 Martin Pieuchot @@ -664,6 +664,7 @@ leave: struct rtable_walk_cookie { int (*rwc_func)(struct rtentry *, void *, unsigned int); void *rwc_arg; + struct rtentry **rwc_prt; unsigned int rwc_rid; }; @@ -679,16 +680,21 @@ rtable_walk_helper(struct art_node *an, void *xrwc) int error = 0; SRPL_FOREACH(rt, &sr, &an->an_rtlist, rt_next) { - if ((error = (*rwc->rwc_func)(rt, rwc->rwc_arg, rwc->rwc_rid))) + error = (*rwc->rwc_func)(rt, rwc->rwc_arg, rwc->rwc_rid); + if (error != 0) break; } + if (rwc->rwc_prt != NULL && rt != NULL) { + rtref(rt); + *rwc->rwc_prt = rt; + } SRPL_LEAVE(&sr); return (error); } int -rtable_walk(unsigned int rtableid, sa_family_t af, +rtable_walk(unsigned int rtableid, sa_family_t af, struct rtentry **prt, int (*func)(struct rtentry *, void *, unsigned int), void *arg) { struct art_root *ar; @@ -701,10 +707,10 @@ rtable_walk(unsigned int rtableid, sa_family_t af, rwc.rwc_func = func; rwc.rwc_arg = arg; + rwc.rwc_prt = prt; rwc.rwc_rid = rtableid; - while ((error = art_walk(ar, rtable_walk_helper, &rwc)) == EAGAIN) - continue; + error = art_walk(ar, rtable_walk_helper, &rwc); return (error); } |