From c5b07695ce810e4345ed1811eadfce935c83b324 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Tue, 7 Jan 2025 11:08:04 +0100 Subject: [PATCH] BGP: fixed deterministic med crashes There were several places of forgotten NULL checks. Thanks to Alarig Le Lay for reporting: https://trubka.network.cz/pipermail/bird-users/2024-December/017990.html --- nest/rt-table.c | 14 ++++++++++++-- proto/bgp/attrs.c | 8 ++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/nest/rt-table.c b/nest/rt-table.c index 05191d74..fc6d0d4e 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -2024,12 +2024,22 @@ rte_recalculate(struct rtable_private *table, struct rt_import_hook *c, struct n do_recalculate: /* Add the new route to the list right behind the old one */ if (new_stored) + { + /* There is the same piece of code several lines farther. Needs refactoring. + * The old_stored check is needed because of the possible jump from deterministic med */ + if (old_stored) { atomic_store_explicit(&new_stored->next, atomic_load_explicit(&old_stored->next, memory_order_relaxed), memory_order_release); atomic_store_explicit(&old_stored->next, new_stored, memory_order_release); - - table->rt_count++; } + else + { + atomic_store_explicit(&new_stored->next, NULL, memory_order_release); + atomic_store_explicit(last_ptr, new_stored, memory_order_release); + } + + table->rt_count++; + } /* Find a new optimal route (if there is any) */ struct rte_storage * _Atomic *bp = &local_sentinel.next; diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 5dc06be5..db654234 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -2689,10 +2689,10 @@ bgp_rte_recalculate(struct rtable_private *table, net *net, struct rte_storage *new_stored, struct rte_storage *old_stored, struct rte_storage *old_best_stored) { struct rte_storage *key_stored = new_stored ? new_stored : old_stored; - const struct rte *new = &new_stored->rte, - *old = &old_stored->rte, - *old_best = &old_best_stored->rte, - *key = &key_stored->rte; + const struct rte *new = RTE_OR_NULL(new_stored), + *old = RTE_OR_NULL(old_stored), + *old_best = RTE_OR_NULL(old_best_stored), + *key = RTE_OR_NULL(key_stored); u32 lpref = rt_get_preference(key); u32 lasn = bgp_get_neighbor(key);