bgpd: evpn_cleanup_local_non_best_route could free dest

But never really does due to locking, but since it can
we need to treat it like it does and ensure that FRR
is not making a mistake, by using memory after it
has been freed.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
This commit is contained in:
Donald Sharp 2023-09-10 09:09:08 -04:00
parent ec8a02af45
commit b45925ad10
3 changed files with 16 additions and 10 deletions

View File

@ -2035,8 +2035,8 @@ static void evpn_zebra_reinstall_best_route(struct bgp *bgp,
* additional handling to prevent bgp from injecting and holding on to a * additional handling to prevent bgp from injecting and holding on to a
* non-best local path. * non-best local path.
*/ */
static void evpn_cleanup_local_non_best_route(struct bgp *bgp, static struct bgp_dest *
struct bgpevpn *vpn, evpn_cleanup_local_non_best_route(struct bgp *bgp, struct bgpevpn *vpn,
struct bgp_dest *dest, struct bgp_dest *dest,
struct bgp_path_info *local_pi) struct bgp_path_info *local_pi)
{ {
@ -2046,10 +2046,11 @@ static void evpn_cleanup_local_non_best_route(struct bgp *bgp,
dest); dest);
evpn_delete_old_local_route(bgp, vpn, dest, local_pi, NULL); evpn_delete_old_local_route(bgp, vpn, dest, local_pi, NULL);
bgp_path_info_reap(dest, local_pi);
/* tell zebra to re-add the best remote path */ /* tell zebra to re-add the best remote path */
evpn_zebra_reinstall_best_route(bgp, vpn, dest); evpn_zebra_reinstall_best_route(bgp, vpn, dest);
return bgp_path_info_reap(dest, local_pi);
} }
static inline bool bgp_evpn_route_add_l3_ecomm_ok(struct bgpevpn *vpn, static inline bool bgp_evpn_route_add_l3_ecomm_ok(struct bgpevpn *vpn,
@ -2186,7 +2187,8 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
} else { } else {
if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) { if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
route_change = 0; route_change = 0;
evpn_cleanup_local_non_best_route(bgp, vpn, dest, pi); dest = evpn_cleanup_local_non_best_route(bgp, vpn, dest,
pi);
} else { } else {
bool new_is_sync; bool new_is_sync;
@ -2203,6 +2205,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
} }
bgp_path_info_unlock(pi); bgp_path_info_unlock(pi);
if (dest)
bgp_dest_unlock_node(dest); bgp_dest_unlock_node(dest);
/* If this is a new route or some attribute has changed, export the /* If this is a new route or some attribute has changed, export the

View File

@ -438,7 +438,8 @@ void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
/* Do the actual removal of info from RIB, for use by bgp_process /* Do the actual removal of info from RIB, for use by bgp_process
completion callback *only* */ completion callback *only* */
void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi) struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest,
struct bgp_path_info *pi)
{ {
if (pi->next) if (pi->next)
pi->next->prev = pi->prev; pi->next->prev = pi->prev;
@ -450,7 +451,8 @@ void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
bgp_path_info_mpath_dequeue(pi); bgp_path_info_mpath_dequeue(pi);
bgp_path_info_unlock(pi); bgp_path_info_unlock(pi);
hook_call(bgp_snmp_update_stats, dest, pi, false); hook_call(bgp_snmp_update_stats, dest, pi, false);
bgp_dest_unlock_node(dest);
return bgp_dest_unlock_node(dest);
} }
void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi) void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)

View File

@ -727,7 +727,8 @@ extern struct bgp_path_info *
bgp_get_imported_bpi_ultimate(struct bgp_path_info *info); bgp_get_imported_bpi_ultimate(struct bgp_path_info *info);
extern void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi); extern void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi);
extern void bgp_path_info_extra_free(struct bgp_path_info_extra **extra); extern void bgp_path_info_extra_free(struct bgp_path_info_extra **extra);
extern void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi); extern struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest,
struct bgp_path_info *pi);
extern void bgp_path_info_delete(struct bgp_dest *dest, extern void bgp_path_info_delete(struct bgp_dest *dest,
struct bgp_path_info *pi); struct bgp_path_info *pi);
extern struct bgp_path_info_extra * extern struct bgp_path_info_extra *