]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: When calling bgp_process, prevent infinite loop
authorDonald Sharp <sharpd@nvidia.com>
Thu, 12 Dec 2024 20:08:35 +0000 (15:08 -0500)
committerMergify <37929162+mergify[bot]@users.noreply.github.com>
Fri, 13 Dec 2024 04:03:45 +0000 (04:03 +0000)
If we have this construct:

for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
     ...
     bgp_process();
}

This can induce an infinite loop.  This happens because bgp_process
will move the unsorted items to the top of the list for handling,
as such it is necessary to hold the next pointer to the side
to actually look at each possible bgp_path_info.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
(cherry picked from commit 40c31bdf4092d45c23fc0e1eed9467015d224d2d)

bgpd/bgp_fsm.c
bgpd/bgp_route.c

index e5692b6b48656540733e0ef13954ef06ed662482..ac33e8a62cfe5606cba44de7bba94b797e78accc 100644 (file)
@@ -661,7 +661,7 @@ static void bgp_llgr_stale_timer_expire(struct event *thread)
 static void bgp_set_llgr_stale(struct peer *peer, afi_t afi, safi_t safi)
 {
        struct bgp_dest *dest;
-       struct bgp_path_info *pi;
+       struct bgp_path_info *pi, *next;
        struct bgp_table *table;
        struct attr attr;
 
@@ -676,8 +676,8 @@ static void bgp_set_llgr_stale(struct peer *peer, afi_t afi, safi_t safi)
 
                        for (rm = bgp_table_top(table); rm;
                             rm = bgp_route_next(rm))
-                               for (pi = bgp_dest_get_bgp_path_info(rm); pi;
-                                    pi = pi->next) {
+                               for (pi = bgp_dest_get_bgp_path_info(rm);
+                                    (pi != NULL) && (next = pi->next, 1); pi = next) {
                                        if (pi->peer != peer)
                                                continue;
 
@@ -708,8 +708,8 @@ static void bgp_set_llgr_stale(struct peer *peer, afi_t afi, safi_t safi)
        } else {
                for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
                     dest = bgp_route_next(dest))
-                       for (pi = bgp_dest_get_bgp_path_info(dest); pi;
-                            pi = pi->next) {
+                       for (pi = bgp_dest_get_bgp_path_info(dest);
+                            (pi != NULL) && (next = pi->next, 1); pi = next) {
                                if (pi->peer != peer)
                                        continue;
 
index 9cadf61c4da75fab94e1fd78898b8761168a00c3..3785d3595413e504d7c4dc312a247ff3afca0546 100644 (file)
@@ -7405,7 +7405,7 @@ static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
 {
        struct bgp_table *table;
        struct bgp_dest *dest;
-       struct bgp_path_info *pi;
+       struct bgp_path_info *pi, *next;
 
        /* Do not install the aggregate route if BGP is in the
         * process of termination.
@@ -7416,7 +7416,8 @@ static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
 
        table = bgp->rib[afi][safi];
        for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
-               for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
+               for (pi = bgp_dest_get_bgp_path_info(dest); (pi != NULL) && (next = pi->next, 1);
+                    pi = next) {
                        if (pi->peer == bgp->peer_self
                            && ((pi->type == ZEBRA_ROUTE_BGP
                                 && pi->sub_type == BGP_ROUTE_STATIC)
@@ -7916,7 +7917,7 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
        struct bgp_table *table = bgp->rib[afi][safi];
        const struct prefix *dest_p;
        struct bgp_dest *dest, *top;
-       struct bgp_path_info *pi;
+       struct bgp_path_info *pi, *next;
 
        /* We've found a different MED we must revert any suppressed routes. */
        top = bgp_node_get(table, p);
@@ -7926,7 +7927,8 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
                if (dest_p->prefixlen <= p->prefixlen)
                        continue;
 
-               for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
+               for (pi = bgp_dest_get_bgp_path_info(dest); (pi != NULL) && (next = pi->next, 1);
+                    pi = next) {
                        if (BGP_PATH_HOLDDOWN(pi))
                                continue;
                        if (pi->sub_type == BGP_ROUTE_AGGREGATE)
@@ -8001,7 +8003,7 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
        struct community *community = NULL;
        struct ecommunity *ecommunity = NULL;
        struct lcommunity *lcommunity = NULL;
-       struct bgp_path_info *pi;
+       struct bgp_path_info *pi, *next;
        uint8_t atomic_aggregate = 0;
 
        /* If the bgp instance is being deleted or self peer is deleted
@@ -8051,7 +8053,8 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
                if (!bgp_check_advertise(bgp, dest, safi))
                        continue;
 
-               for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
+               for (pi = bgp_dest_get_bgp_path_info(dest); (pi != NULL) && (next = pi->next, 1);
+                    pi = next) {
                        if (BGP_PATH_HOLDDOWN(pi))
                                continue;
 
@@ -8209,7 +8212,7 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
        struct bgp_table *table;
        struct bgp_dest *top;
        struct bgp_dest *dest;
-       struct bgp_path_info *pi;
+       struct bgp_path_info *pi, *next;
 
        table = bgp->rib[afi][safi];
 
@@ -8222,7 +8225,8 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
                if (dest_p->prefixlen <= p->prefixlen)
                        continue;
 
-               for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
+               for (pi = bgp_dest_get_bgp_path_info(dest); (pi != NULL) && (next = pi->next, 1);
+                    pi = next) {
                        if (BGP_PATH_HOLDDOWN(pi))
                                continue;