From: Donald Sharp Date: Wed, 17 Oct 2018 15:27:30 +0000 (-0400) Subject: bgpd: Fix crash when using v4 route w/ v6 nexthop X-Git-Tag: frr-7.1-dev~262^2~1 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=7f040da1a18981277a1db29764a3dc6f0e7d2f10;p=matthieu%2Ffrr.git bgpd: Fix crash when using v4 route w/ v6 nexthop Recent changes to the nht code in bgp caused us to actually keep a true count of v6 nexthop paths when using v4 over v6. This change introduced a race condition on shutdown on who got to the bnc cache first( the v4 table or not ). Effectively we were allowing the continued existence of the path->nexthop pointing to the freed bnc. This was especially true when we had route leaking. So when we free the bnc make sure we clean up the path->nexthop variables pointing at it too. Signed-off-by: Donald Sharp --- diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 45c596254f..be219d2374 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -85,6 +85,13 @@ static void bgp_nexthop_cache_reset(struct bgp_table *table) for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { bnc = bgp_nexthop_get_node_info(rn); if (bnc != NULL) { + while (!LIST_EMPTY(&(bnc->paths))) { + struct bgp_path_info *path = + LIST_FIRST(&(bnc->paths)); + + path_nh_map(path, bnc, false); + } + bnc_free(bnc); bgp_nexthop_set_node_info(rn, NULL); bgp_unlock_node(rn); diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 5203e6eefd..e764860bcc 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -51,8 +51,6 @@ static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc, int is_bgp_static_route); static void evaluate_paths(struct bgp_nexthop_cache *bnc); static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p); -static void path_nh_map(struct bgp_path_info *path, - struct bgp_nexthop_cache *bnc, int keep); static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc) { @@ -111,7 +109,7 @@ void bgp_unlink_nexthop(struct bgp_path_info *path) if (!bnc) return; - path_nh_map(path, NULL, 0); + path_nh_map(path, NULL, false); bgp_unlink_nexthop_check(bnc); } @@ -253,7 +251,8 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, */ bgp_unlink_nexthop(pi); - path_nh_map(pi, bnc, 1); /* updates NHT pi list reference */ + /* updates NHT pi list reference */ + path_nh_map(pi, bnc, true); if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric) (bgp_path_info_extra_get(pi))->igpmetric = bnc->metric; @@ -789,8 +788,8 @@ static void evaluate_paths(struct bgp_nexthop_cache *bnc) * make - if set, make the association. if unset, just break the existing * association. */ -static void path_nh_map(struct bgp_path_info *path, - struct bgp_nexthop_cache *bnc, int make) +void path_nh_map(struct bgp_path_info *path, struct bgp_nexthop_cache *bnc, + bool make) { if (path->nexthop) { LIST_REMOVE(path, nh_thread); diff --git a/bgpd/bgp_nht.h b/bgpd/bgp_nht.h index 7b29fa818f..0cc045a065 100644 --- a/bgpd/bgp_nht.h +++ b/bgpd/bgp_nht.h @@ -75,4 +75,11 @@ extern void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer); */ extern void bgp_cleanup_nexthops(struct bgp *bgp); +/* + * Add or remove the tracking of the bgp_path_info that + * uses this nexthop + */ +extern void path_nh_map(struct bgp_path_info *path, + struct bgp_nexthop_cache *bnc, bool make); + #endif /* _BGP_NHT_H */