diff --git a/meta-networking/recipes-protocols/frr/frr/CVE-2024-55553.patch b/meta-networking/recipes-protocols/frr/frr/CVE-2024-55553.patch new file mode 100644 index 0000000000..ac8dbcc2ed --- /dev/null +++ b/meta-networking/recipes-protocols/frr/frr/CVE-2024-55553.patch @@ -0,0 +1,253 @@ +From c66b72ef6d10f3f77d4bdddd849436a16270dfc4 Mon Sep 17 00:00:00 2001 +From: Donatas Abraitis +Date: Wed, 4 Dec 2024 23:38:34 +0200 +Subject: [PATCH] bgpd: Validate only affected RPKI prefixes instead of a full + RIB + +Before this fix, if rpki_sync_socket_rtr socket returns EAGAIN, then ALL routes +in the RIB are revalidated which takes lots of CPU and some unnecessary traffic, +e.g. if using BMP servers. With a full feed it would waste 50-80Mbps. + +Instead we should try to drain an existing pipe (another end), and revalidate +only affected prefixes. + +Signed-off-by: Donatas Abraitis + +CVE: CVE-2024-55553 +Upstream-Status: Backport [https://github.com/FRRouting/frr/commit/b0800bfdf04b4fcf48504737ebfe4ba7f05268d3] +Signed-off-by: Zhang Peng +--- + bgpd/bgp_rpki.c | 148 ++++++++++++++++++------------------------------ + bgpd/bgpd.c | 4 -- + bgpd/bgpd.h | 1 - + 3 files changed, 55 insertions(+), 98 deletions(-) + +diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c +index 375b041853..402ff24b50 100644 +--- a/bgpd/bgp_rpki.c ++++ b/bgpd/bgp_rpki.c +@@ -116,7 +116,6 @@ static enum route_map_cmd_result_t route_match(void *rule, + void *object); + static void *route_match_compile(const char *arg); + static void revalidate_bgp_node(struct bgp_dest *dest, afi_t afi, safi_t safi); +-static void revalidate_all_routes(void); + + static struct rtr_mgr_config *rtr_config; + static struct list *cache_list; +@@ -403,36 +402,10 @@ static void rpki_revalidate_prefix(struct event *thread) + XFREE(MTYPE_BGP_RPKI_REVALIDATE, rrp); + } + +-static void bgpd_sync_callback(struct event *thread) ++static void revalidate_single_prefix(struct vrf *vrf, struct prefix prefix, afi_t afi) + { + struct bgp *bgp; + struct listnode *node; +- struct prefix prefix; +- struct pfx_record rec; +- +- event_add_read(bm->master, bgpd_sync_callback, NULL, +- rpki_sync_socket_bgpd, NULL); +- +- if (atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst)) { +- while (read(rpki_sync_socket_bgpd, &rec, +- sizeof(struct pfx_record)) != -1) +- ; +- +- atomic_store_explicit(&rtr_update_overflow, 0, +- memory_order_seq_cst); +- revalidate_all_routes(); +- return; +- } +- +- int retval = +- read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record)); +- if (retval != sizeof(struct pfx_record)) { +- RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd"); +- return; +- } +- pfx_record_to_prefix(&rec, &prefix); +- +- afi_t afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6; + + for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) { + safi_t safi; +@@ -455,87 +428,76 @@ static void bgpd_sync_callback(struct event *thread) + } + } + +-static void revalidate_bgp_node(struct bgp_dest *bgp_dest, afi_t afi, +- safi_t safi) ++static void bgpd_sync_callback(struct event *thread) + { +- struct bgp_adj_in *ain; ++ struct prefix prefix; ++ struct pfx_record rec; ++ struct rpki_vrf *rpki_vrf = EVENT_ARG(thread); ++ struct vrf *vrf = NULL; ++ afi_t afi; ++ int retval; + +- for (ain = bgp_dest->adj_in; ain; ain = ain->next) { +- struct bgp_path_info *path = +- bgp_dest_get_bgp_path_info(bgp_dest); +- mpls_label_t *label = NULL; +- uint32_t num_labels = 0; +- +- if (path && path->extra) { +- label = path->extra->label; +- num_labels = path->extra->num_labels; ++ event_add_read(bm->master, bgpd_sync_callback, rpki_vrf, rpki_vrf->rpki_sync_socket_bgpd, ++ NULL); ++ ++ if (rpki_vrf->vrfname) { ++ vrf = vrf_lookup_by_name(rpki_vrf->vrfname); ++ if (!vrf) { ++ zlog_err("%s(): vrf for rpki %s not found", __func__, rpki_vrf->vrfname); ++ return; + } +- (void)bgp_update(ain->peer, bgp_dest_get_prefix(bgp_dest), +- ain->addpath_rx_id, ain->attr, afi, safi, +- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, label, +- num_labels, 1, NULL); + } +-} + +-/* +- * The act of a soft reconfig in revalidation is really expensive +- * coupled with the fact that the download of a full rpki state +- * from a rpki server can be expensive, let's break up the revalidation +- * to a point in time in the future to allow other bgp events +- * to take place too. +- */ +-struct rpki_revalidate_peer { +- afi_t afi; +- safi_t safi; +- struct peer *peer; +-}; ++ if (atomic_load_explicit(&rpki_vrf->rtr_update_overflow, memory_order_seq_cst)) { ++ ssize_t size = 0; + +-static void bgp_rpki_revalidate_peer(struct event *thread) +-{ +- struct rpki_revalidate_peer *rvp = EVENT_ARG(thread); ++ retval = read(rpki_vrf->rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record)); ++ while (retval != -1) { ++ if (retval != sizeof(struct pfx_record)) ++ break; + +- /* +- * Here's the expensive bit of gnomish deviousness +- */ +- bgp_soft_reconfig_in(rvp->peer, rvp->afi, rvp->safi); ++ size += retval; ++ pfx_record_to_prefix(&rec, &prefix); ++ afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6; ++ revalidate_single_prefix(vrf, prefix, afi); + +- XFREE(MTYPE_BGP_RPKI_REVALIDATE, rvp); +-} ++ retval = read(rpki_vrf->rpki_sync_socket_bgpd, &rec, ++ sizeof(struct pfx_record)); ++ } + +-static void revalidate_all_routes(void) +-{ +- struct bgp *bgp; +- struct listnode *node; ++ RPKI_DEBUG("Socket overflow detected (%zu), revalidating affected prefixes", size); + +- for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) { +- struct peer *peer; +- struct listnode *peer_listnode; ++ atomic_store_explicit(&rpki_vrf->rtr_update_overflow, 0, memory_order_seq_cst); ++ return; ++ } + +- for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) { +- afi_t afi; +- safi_t safi; ++ retval = read(rpki_vrf->rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record)); ++ if (retval != sizeof(struct pfx_record)) { ++ RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd"); ++ return; ++ } ++ pfx_record_to_prefix(&rec, &prefix); + +- FOREACH_AFI_SAFI (afi, safi) { +- struct rpki_revalidate_peer *rvp; ++ afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6; + +- if (!bgp->rib[afi][safi]) +- continue; ++ revalidate_single_prefix(vrf, prefix, afi); ++} + +- if (!peer_established(peer->connection)) +- continue; ++static void revalidate_bgp_node(struct bgp_dest *bgp_dest, afi_t afi, safi_t safi) ++{ ++ struct bgp_adj_in *ain; ++ mpls_label_t *label; ++ uint8_t num_labels; ++ ++ for (ain = bgp_dest->adj_in; ain; ain = ain->next) { ++ struct bgp_path_info *path = bgp_dest_get_bgp_path_info(bgp_dest); + +- rvp = XCALLOC(MTYPE_BGP_RPKI_REVALIDATE, +- sizeof(*rvp)); +- rvp->peer = peer; +- rvp->afi = afi; +- rvp->safi = safi; ++ num_labels = BGP_PATH_INFO_NUM_LABELS(path); ++ label = num_labels ? path->extra->labels->label : NULL; + +- event_add_event( +- bm->master, bgp_rpki_revalidate_peer, +- rvp, 0, +- &peer->t_revalidate_all[afi][safi]); +- } +- } ++ (void)bgp_update(ain->peer, bgp_dest_get_prefix(bgp_dest), ain->addpath_rx_id, ++ ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, ++ label, num_labels, 1, NULL); + } + } + +diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c +index 4de5964c39..9bf964c45f 100644 +--- a/bgpd/bgpd.c ++++ b/bgpd/bgpd.c +@@ -1248,8 +1248,6 @@ static void peer_free(struct peer *peer) + bgp_reads_off(peer->connection); + bgp_writes_off(peer->connection); + event_cancel_event_ready(bm->master, peer->connection); +- FOREACH_AFI_SAFI (afi, safi) +- EVENT_OFF(peer->t_revalidate_all[afi][safi]); + assert(!peer->connection->t_write); + assert(!peer->connection->t_read); + event_cancel_event_ready(bm->master, peer->connection); +@@ -2640,8 +2638,6 @@ int peer_delete(struct peer *peer) + bgp_reads_off(peer->connection); + bgp_writes_off(peer->connection); + event_cancel_event_ready(bm->master, peer->connection); +- FOREACH_AFI_SAFI (afi, safi) +- EVENT_OFF(peer->t_revalidate_all[afi][safi]); + assert(!CHECK_FLAG(peer->connection->thread_flags, + PEER_THREAD_WRITES_ON)); + assert(!CHECK_FLAG(peer->connection->thread_flags, +diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h +index b139b2c1b4..c4faacc6dc 100644 +--- a/bgpd/bgpd.h ++++ b/bgpd/bgpd.h +@@ -1571,7 +1571,6 @@ struct peer { + + /* Threads. */ + struct event *t_llgr_stale[AFI_MAX][SAFI_MAX]; +- struct event *t_revalidate_all[AFI_MAX][SAFI_MAX]; + struct event *t_refresh_stalepath; + + /* Thread flags. */ +-- +2.50.0 + diff --git a/meta-networking/recipes-protocols/frr/frr_9.1.3.bb b/meta-networking/recipes-protocols/frr/frr_9.1.3.bb index f3b4816941..c5f626a35a 100644 --- a/meta-networking/recipes-protocols/frr/frr_9.1.3.bb +++ b/meta-networking/recipes-protocols/frr/frr_9.1.3.bb @@ -13,6 +13,7 @@ LIC_FILES_CHKSUM = "file://doc/licenses/GPL-2.0;md5=b234ee4d69f5fce4486a80fdaf4a SRC_URI = "git://github.com/FRRouting/frr.git;protocol=https;branch=stable/9.1 \ file://frr.pam \ file://0001-zebra-Mimic-GNU-basename-API-for-non-glibc-library-e.patch \ + file://CVE-2024-55553.patch \ " SRCREV = "ad1766d17be022587fe05ebe1a7bf10e1b7dce19"