Skip to content

Commit addff17

Browse files
committed
bgpd: Ensure community data is freed in some cases.
Customer has this valgrind trace: Direct leak of 2829120 byte(s) in 70728 object(s) allocated from: 0 in community_new ../bgpd/bgp_community.c:39 1 in community_uniq_sort ../bgpd/bgp_community.c:170 2 in route_set_community ../bgpd/bgp_routemap.c:2342 3 in route_map_apply_ext ../lib/routemap.c:2673 4 in subgroup_announce_check ../bgpd/bgp_route.c:2367 5 in subgroup_process_announce_selected ../bgpd/bgp_route.c:2914 6 in group_announce_route_walkcb ../bgpd/bgp_updgrp_adv.c:199 7 in hash_walk ../lib/hash.c:285 8 in update_group_af_walk ../bgpd/bgp_updgrp.c:2061 9 in group_announce_route ../bgpd/bgp_updgrp_adv.c:1059 10 in bgp_process_main_one ../bgpd/bgp_route.c:3221 11 in bgp_process_wq ../bgpd/bgp_route.c:3221 12 in work_queue_run ../lib/workqueue.c:282 The above leak detected by valgrind was from a screenshot so I copied it by hand. Any mistakes in line numbers are purely from my transcription. Additionally this is against a slightly modified 8.5.1 version of FRR. Code inspection of 8.5.1 -vs- latest master shows the same problem exists. Code should be able to be followed from there to here. What is happening: There is a route-map being applied that modifes the outgoing community to a peer. This is saved in the attr copy created in subgroup_process_announce_selected. This community pointer is not interned. So the community->refcount is still 0. Normally when a prefix is announced, the attr and the prefix are placed on a adjency out structure where the attribute is interned. This will cause the community to be saved in the community hash list as well. In a non-normal operation when the decision to send is aborted after the route-map application, the attribute is just dropped and the pointer to the community is just dropped too, leading to situations where the memory is leaked. The usage of bgp suppress-fib would would be a case where the community is caused to be leaked. Additionally the previous commit where an unsuppress-map is used to modify the outgoing attribute but since unsuppress-map was not considered part of outgoing policy the attribute would be dropped as well. This pointer drop also extends to any dynamically allocated memory saved by the attribute pointer that was not interned yet as well. So let's modify the return case where the decision is made to not send the prefix to the peer to always just flush the attribute to ensure memory is not leaked. Fixes: #15459 Signed-off-by: Donald Sharp <[email protected]>
1 parent 6814401 commit addff17

File tree

4 files changed

+39
-31
lines changed

4 files changed

+39
-31
lines changed

bgpd/bgp_conditional_adv.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,9 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
122122
if (update_type == UPDATE_TYPE_ADVERTISE &&
123123
subgroup_announce_check(dest, pi, subgrp, dest_p,
124124
&attr, &advmap_attr)) {
125-
bgp_adj_out_set_subgroup(dest, subgrp, &attr,
126-
pi);
125+
if (!bgp_adj_out_set_subgroup(dest, subgrp,
126+
&attr, pi))
127+
bgp_attr_flush(&attr);
127128
} else {
128129
/* If default originate is enabled for
129130
* the peer, do not send explicit

bgpd/bgp_route.c

+15-11
Original file line numberDiff line numberDiff line change
@@ -2979,7 +2979,7 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp,
29792979
{
29802980
const struct prefix *p;
29812981
struct peer *onlypeer;
2982-
struct attr attr;
2982+
struct attr attr = { 0 }, *pattr = &attr;
29832983
struct bgp *bgp;
29842984
bool advertise;
29852985

@@ -3007,26 +3007,30 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp,
30073007
advertise = bgp_check_advertise(bgp, dest, safi);
30083008

30093009
if (selected) {
3010-
if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
3010+
if (subgroup_announce_check(dest, selected, subgrp, p, pattr,
30113011
NULL)) {
30123012
/* Route is selected, if the route is already installed
30133013
* in FIB, then it is advertised
30143014
*/
30153015
if (advertise) {
30163016
if (!bgp_check_withdrawal(bgp, dest, safi)) {
3017-
struct attr *adv_attr =
3018-
bgp_attr_intern(&attr);
3019-
3020-
bgp_adj_out_set_subgroup(dest, subgrp,
3021-
adv_attr,
3022-
selected);
3023-
} else
3017+
if (!bgp_adj_out_set_subgroup(dest,
3018+
subgrp,
3019+
pattr,
3020+
selected))
3021+
bgp_attr_flush(pattr);
3022+
} else {
30243023
bgp_adj_out_unset_subgroup(
30253024
dest, subgrp, 1, addpath_tx_id);
3026-
}
3027-
} else
3025+
bgp_attr_flush(pattr);
3026+
}
3027+
} else
3028+
bgp_attr_flush(pattr);
3029+
} else {
30283030
bgp_adj_out_unset_subgroup(dest, subgrp, 1,
30293031
addpath_tx_id);
3032+
bgp_attr_flush(pattr);
3033+
}
30303034
}
30313035

30323036
/* If selected is NULL we must withdraw the path using addpath_tx_id */

bgpd/bgp_updgrp.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ extern struct bgp_adj_out *bgp_adj_out_alloc(struct update_subgroup *subgrp,
441441
extern void bgp_adj_out_remove_subgroup(struct bgp_dest *dest,
442442
struct bgp_adj_out *adj,
443443
struct update_subgroup *subgrp);
444-
extern void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
444+
extern bool bgp_adj_out_set_subgroup(struct bgp_dest *dest,
445445
struct update_subgroup *subgrp,
446446
struct attr *attr,
447447
struct bgp_path_info *path);

bgpd/bgp_updgrp_adv.c

+20-17
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ bgp_advertise_clean_subgroup(struct update_subgroup *subgrp,
520520
return next;
521521
}
522522

523-
void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
523+
bool bgp_adj_out_set_subgroup(struct bgp_dest *dest,
524524
struct update_subgroup *subgrp, struct attr *attr,
525525
struct bgp_path_info *path)
526526
{
@@ -540,7 +540,7 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
540540
bgp = SUBGRP_INST(subgrp);
541541

542542
if (DISABLE_BGP_ANNOUNCE)
543-
return;
543+
return false;
544544

545545
/* Look for adjacency information. */
546546
adj = adj_lookup(
@@ -556,7 +556,7 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
556556
bgp_addpath_id_for_peer(peer, afi, safi,
557557
&path->tx_addpath));
558558
if (!adj)
559-
return;
559+
return false;
560560

561561
subgrp->pscount++;
562562
}
@@ -595,7 +595,7 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
595595
* will never be able to coalesce the 3rd peer down
596596
*/
597597
subgrp->version = MAX(subgrp->version, dest->version);
598-
return;
598+
return false;
599599
}
600600

601601
if (adj->adv)
@@ -643,6 +643,8 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
643643
bgp_adv_fifo_add_tail(&subgrp->sync->update, adv);
644644

645645
subgrp->version = MAX(subgrp->version, dest->version);
646+
647+
return true;
646648
}
647649

648650
/* The only time 'withdraw' will be false is if we are sending
@@ -852,7 +854,7 @@ void subgroup_announce_route(struct update_subgroup *subgrp)
852854
void subgroup_default_originate(struct update_subgroup *subgrp, bool withdraw)
853855
{
854856
struct bgp *bgp;
855-
struct attr attr;
857+
struct attr attr = { 0 };
856858
struct attr *new_attr = &attr;
857859
struct aspath *aspath;
858860
struct prefix p;
@@ -993,18 +995,19 @@ void subgroup_default_originate(struct update_subgroup *subgrp, bool withdraw)
993995
if (dest) {
994996
for (pi = bgp_dest_get_bgp_path_info(dest); pi;
995997
pi = pi->next) {
996-
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
997-
if (subgroup_announce_check(
998-
dest, pi, subgrp,
999-
bgp_dest_get_prefix(dest),
1000-
&attr, NULL)) {
1001-
struct attr *default_attr =
1002-
bgp_attr_intern(&attr);
1003-
1004-
bgp_adj_out_set_subgroup(
1005-
dest, subgrp,
1006-
default_attr, pi);
1007-
}
998+
if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
999+
continue;
1000+
1001+
if (subgroup_announce_check(dest, pi, subgrp,
1002+
bgp_dest_get_prefix(
1003+
dest),
1004+
&attr, NULL)) {
1005+
if (!bgp_adj_out_set_subgroup(dest,
1006+
subgrp,
1007+
&attr, pi))
1008+
bgp_attr_flush(&attr);
1009+
} else
1010+
bgp_attr_flush(&attr);
10081011
}
10091012
bgp_dest_unlock_node(dest);
10101013
}

0 commit comments

Comments
 (0)