Import from AlmaLinux stable repository

This commit is contained in:
eabdullin 2024-05-31 16:38:12 +00:00
parent 5788752ec0
commit 636018dbc7
19 changed files with 1578 additions and 5 deletions

View File

@ -1,2 +0,0 @@
dfc756dfd123360d1e1a760d66821e47f9a6afed SOURCES/frr-7.5.1.tar.gz
e25979fad0e873cd0196e528cae570ba18c11a8f SOURCES/frr.if

1
.gitignore vendored
View File

@ -1,2 +1 @@
SOURCES/frr-7.5.1.tar.gz
SOURCES/frr.if

View File

@ -0,0 +1,117 @@
From 4b793d1eb35ab5794db12725a28fcdb4fef23af7 Mon Sep 17 00:00:00 2001
From: Igor Ryzhov <iryzhov@nfware.com>
Date: Thu, 1 Apr 2021 15:29:18 +0300
Subject: [PATCH] bfdd: remove profiles when removing bfd node
Fixes #8379.
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
---
bfdd/bfd.c | 8 ++++++++
bfdd/bfd.h | 1 +
bfdd/bfdd_nb_config.c | 1 +
3 files changed, 10 insertions(+)
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index c966efd8ea71..cf292a836354 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -1889,6 +1889,14 @@ void bfd_sessions_remove_manual(void)
hash_iterate(bfd_key_hash, _bfd_session_remove_manual, NULL);
}
+void bfd_profiles_remove(void)
+{
+ struct bfd_profile *bp;
+
+ while ((bp = TAILQ_FIRST(&bplist)) != NULL)
+ bfd_profile_free(bp);
+}
+
/*
* Profile related hash functions.
*/
diff --git a/bfdd/bfd.h b/bfdd/bfd.h
index af3f92d6a8f8..9ee1da728717 100644
--- a/bfdd/bfd.h
+++ b/bfdd/bfd.h
@@ -596,6 +596,7 @@ void bfd_session_free(struct bfd_session *bs);
const struct bfd_session *bfd_session_next(const struct bfd_session *bs,
bool mhop);
void bfd_sessions_remove_manual(void);
+void bfd_profiles_remove(void);
/**
* Set the BFD session echo state.
diff --git a/bfdd/bfdd_nb_config.c b/bfdd/bfdd_nb_config.c
index 0046bc625b45..77f8cbd09c07 100644
--- a/bfdd/bfdd_nb_config.c
+++ b/bfdd/bfdd_nb_config.c
@@ -203,6 +203,7 @@ int bfdd_bfd_destroy(struct nb_cb_destroy_args *args)
case NB_EV_APPLY:
bfd_sessions_remove_manual();
+ bfd_profiles_remove();
break;
case NB_EV_ABORT:
diff --git a/bfdd/bfdd_nb_config.c b/bfdd/bfdd_nb_config.c
index 77f8cbd09c07..4030e2eefa50 100644
--- a/bfdd/bfdd_nb_config.c
+++ b/bfdd/bfdd_nb_config.c
@@ -186,7 +186,15 @@ static int bfd_session_destroy(enum nb_event event,
*/
int bfdd_bfd_create(struct nb_cb_create_args *args)
{
- /* NOTHING */
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ /*
+ * Set any non-NULL value to be able to call
+ * nb_running_unset_entry in bfdd_bfd_destroy.
+ */
+ nb_running_set_entry(args->dnode, (void *)0x1);
+
return NB_OK;
}
@@ -202,6 +210,12 @@ int bfdd_bfd_destroy(struct nb_cb_destroy_args *args)
return NB_OK;
case NB_EV_APPLY:
+ /*
+ * We need to call this to unset pointers from
+ * the child nodes - sessions and profiles.
+ */
+ nb_running_unset_entry(args->dnode);
+
bfd_sessions_remove_manual();
bfd_profiles_remove();
break;
diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c
index b64e36b36a44..5a844e56e121 100644
--- a/bfdd/bfdd_cli.c
+++ b/bfdd/bfdd_cli.c
@@ -486,7 +486,7 @@ void bfd_cli_show_echo_interval(struct vty *vty, struct lyd_node *dnode,
* Profile commands.
*/
DEFPY_YANG_NOSH(bfd_profile, bfd_profile_cmd,
- "profile WORD$name",
+ "profile BFDPROF$name",
BFD_PROFILE_STR
BFD_PROFILE_NAME_STR)
{
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 74f13e1a44e8..cf1811bb1f2f 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -1959,7 +1959,7 @@ DEFUNSH(VTYSH_BFDD, bfd_peer_enter, bfd_peer_enter_cmd,
}
DEFUNSH(VTYSH_BFDD, bfd_profile_enter, bfd_profile_enter_cmd,
- "profile WORD",
+ "profile BFDPROF",
BFD_PROFILE_STR
BFD_PROFILE_NAME_STR)
{

View File

@ -0,0 +1,93 @@
From 767aaa3a80489bfc4ff097f932fc347e3db25b89 Mon Sep 17 00:00:00 2001
From: Donatas Abraitis <donatas@opensourcerouting.org>
Date: Mon, 21 Aug 2023 00:01:42 +0300
Subject: [PATCH] bgpd: Do not explicitly print MAXTTL value for ebgp-multihop
vty output
1. Create /etc/frr/frr.conf
```
frr version 7.5
frr defaults traditional
hostname centos8.localdomain
no ip forwarding
no ipv6 forwarding
service integrated-vtysh-config
line vty
router bgp 4250001000
neighbor 192.168.122.207 remote-as 65512
neighbor 192.168.122.207 ebgp-multihop
```
2. Start FRR
`# systemctl start frr
`
3. Show running configuration. Note that FRR explicitly set and shows the default TTL (225)
```
Building configuration...
Current configuration:
!
frr version 7.5
frr defaults traditional
hostname centos8.localdomain
no ip forwarding
no ipv6 forwarding
service integrated-vtysh-config
!
router bgp 4250001000
neighbor 192.168.122.207 remote-as 65512
neighbor 192.168.122.207 ebgp-multihop 255
!
line vty
!
end
```
4. Copy initial frr.conf to frr.conf.new (no changes)
`# cp /etc/frr/frr.conf /root/frr.conf.new
`
5. Run frr-reload.sh:
```
$ /usr/lib/frr/frr-reload.py --test /root/frr.conf.new
2023-08-20 20:15:48,050 INFO: Called via "Namespace(bindir='/usr/bin', confdir='/etc/frr', daemon='', debug=False, filename='/root/frr.conf.new', input=None, log_level='info', overwrite=False, pathspace=None, reload=False, rundir='/var/run/frr', stdout=False, test=True, vty_socket=None)"
2023-08-20 20:15:48,050 INFO: Loading Config object from file /root/frr.conf.new
2023-08-20 20:15:48,124 INFO: Loading Config object from vtysh show running
Lines To Delete
===============
router bgp 4250001000
no neighbor 192.168.122.207 ebgp-multihop 255
Lines To Add
============
router bgp 4250001000
neighbor 192.168.122.207 ebgp-multihop
```
Closes https://github.com/FRRouting/frr/issues/14242
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
---
bgpd/bgp_vty.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index be0fe4283747..c9a9255f3392 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -17735,8 +17735,12 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
&& !(peer->gtsm_hops != BGP_GTSM_HOPS_DISABLED
&& peer->ttl == MAXTTL)) {
if (!peer_group_active(peer) || g_peer->ttl != peer->ttl) {
- vty_out(vty, " neighbor %s ebgp-multihop %d\n", addr,
- peer->ttl);
+ if (peer->ttl != MAXTTL)
+ vty_out(vty, " neighbor %s ebgp-multihop %d\n",
+ addr, peer->ttl);
+ else
+ vty_out(vty, " neighbor %s ebgp-multihop\n",
+ addr);
}
}

View File

@ -0,0 +1,129 @@
From 46817adab03802355c3cce7b753c7a735bdcc5ae Mon Sep 17 00:00:00 2001
From: Donatas Abraitis <donatas@opensourcerouting.org>
Date: Thu, 13 Jul 2023 22:32:03 +0300
Subject: [PATCH] bgpd: Use treat-as-withdraw for tunnel encapsulation
attribute
Before this path we used session reset method, which is discouraged by rfc7606.
Handle this as rfc requires.
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
(cherry picked from commit bcb6b58d9530173df41d3a3cbc4c600ee0b4b186)
---
bgpd/bgp_attr.c | 61 ++++++++++++++++++++-----------------------------
1 file changed, 25 insertions(+), 36 deletions(-)
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 058fae23cbd..1c0803cfd8e 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -1301,6 +1301,7 @@ bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
case BGP_ATTR_LARGE_COMMUNITIES:
case BGP_ATTR_ORIGINATOR_ID:
case BGP_ATTR_CLUSTER_LIST:
+ case BGP_ATTR_ENCAP:
return BGP_ATTR_PARSE_WITHDRAW;
case BGP_ATTR_MP_REACH_NLRI:
case BGP_ATTR_MP_UNREACH_NLRI:
@@ -2434,26 +2435,21 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
}
/* Parse Tunnel Encap attribute in an UPDATE */
-static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
- bgp_size_t length, /* IN: attr's length field */
- struct attr *attr, /* IN: caller already allocated */
- uint8_t flag, /* IN: attr's flags field */
- uint8_t *startp)
+static int bgp_attr_encap(struct bgp_attr_parser_args *args)
{
- bgp_size_t total;
uint16_t tunneltype = 0;
-
- total = length + (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+ struct peer *const peer = args->peer;
+ struct attr *const attr = args->attr;
+ bgp_size_t length = args->length;
+ uint8_t type = args->type;
+ uint8_t flag = args->flags;
if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
|| !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) {
- zlog_info(
- "Tunnel Encap attribute flag isn't optional and transitive %d",
- flag);
- bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
- startp, total);
- return -1;
+ zlog_err("Tunnel Encap attribute flag isn't optional and transitive %d",
+ flag);
+ return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+ args->total);
}
if (BGP_ATTR_ENCAP == type) {
@@ -2461,12 +2457,11 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
uint16_t tlv_length;
if (length < 4) {
- zlog_info(
+ zlog_err(
"Tunnel Encap attribute not long enough to contain outer T,L");
- bgp_notify_send_with_data(
- peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, startp, total);
- return -1;
+ return bgp_attr_malformed(args,
+ BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+ args->total);
}
tunneltype = stream_getw(BGP_INPUT(peer));
tlv_length = stream_getw(BGP_INPUT(peer));
@@ -2496,13 +2491,11 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
}
if (sublength > length) {
- zlog_info(
- "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
- sublength, length);
- bgp_notify_send_with_data(
- peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, startp, total);
- return -1;
+ zlog_err("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
+ sublength, length);
+ return bgp_attr_malformed(args,
+ BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+ args->total);
}
/* alloc and copy sub-tlv */
@@ -2550,13 +2543,10 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
if (length) {
/* spurious leftover data */
- zlog_info(
- "Tunnel Encap attribute length is bad: %d leftover octets",
- length);
- bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
- startp, total);
- return -1;
+ zlog_err("Tunnel Encap attribute length is bad: %d leftover octets",
+ length);
+ return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+ args->total);
}
return 0;
@@ -3396,8 +3386,7 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
case BGP_ATTR_VNC:
#endif
case BGP_ATTR_ENCAP:
- ret = bgp_attr_encap(type, peer, length, attr, flag,
- startp);
+ ret = bgp_attr_encap(&attr_args);
break;
case BGP_ATTR_PREFIX_SID:
ret = bgp_attr_prefix_sid(&attr_args);

View File

@ -0,0 +1,48 @@
From 0f9e4c4a36cf2b0dd585a7ef97acccb8eebdf7bd Mon Sep 17 00:00:00 2001
From: Chirag Shah <chirag@nvidia.com>
Date: Mon, 25 Jan 2021 11:44:56 -0800
Subject: [PATCH] lib: fix a crash in plist update
Problem:
Prefix-list with mulitiple rules, an update to
a rule/sequence with different prefix/prefixlen
reset prefix-list next-base pointer to avoid
having stale value.
In some case the old next-bast's reference leads
to an assert in tri (trie_install_fn ) add.
bt:
(object=0x55576a4c8a00, updptr=0x55576a4b97e0) at lib/plist.c:560
(plist=0x55576a4a1770, pentry=0x55576a4c8a00) at lib/plist.c:585
(ple=0x55576a4c8a00) at lib/plist.c:745
(args=0x7fffe04beb50) at lib/filter_nb.c:1181
Solution:
Reset prefix-list next-base pointer whenver a
sequence/rule is updated.
Ticket:CM-33109
Testing Done:
Signed-off-by: Chirag Shah <chirag@nvidia.com>
Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
(cherry picked from commit f7f101156eb0e225f375f12cf4f863ebbe3fed03)
---
lib/plist.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/plist.c b/lib/plist.c
index 981e86e2a..c746d1946 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -684,6 +684,7 @@ void prefix_list_entry_update_start(struct prefix_list_entry *ple)
if (pl->head || pl->tail || pl->desc)
pl->master->recent = pl;
+ ple->next_best = NULL;
ple->installed = false;
}
--
2.41.0

View File

@ -0,0 +1,34 @@
From 0b999c886e241c52bd1f7ef0066700e4b618ebb3 Mon Sep 17 00:00:00 2001
From: Donald Sharp <sharpd@nvidia.com>
Date: Thu, 23 Feb 2023 13:29:32 -0500
Subject: [PATCH] bgpd: Flowspec overflow issue
According to the flowspec RFC 8955 a flowspec nlri is <length, <nlri data>>
Specifying 0 as a length makes BGP get all warm on the inside. Which
in this case is not a good thing at all. Prevent warmth, stay cold
on the inside.
Reported-by: Iggy Frankovic <iggyfran@amazon.com>
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
---
bgpd/bgp_flowspec.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c
index 8d5ca5e77779..f9debe43cd45 100644
--- a/bgpd/bgp_flowspec.c
+++ b/bgpd/bgp_flowspec.c
@@ -127,6 +127,13 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
psize);
return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
}
+
+ if (psize == 0) {
+ flog_err(EC_BGP_FLOWSPEC_PACKET,
+ "Flowspec NLRI length 0 which makes no sense");
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
+ }
+
if (bgp_fs_nlri_validate(pnt, psize, afi) < 0) {
flog_err(
EC_BGP_FLOWSPEC_PACKET,

View File

@ -0,0 +1,54 @@
From 7404a914b0cafe046703c8381903a80d3def8f8b Mon Sep 17 00:00:00 2001
From: Donald Sharp <sharpd@nvidia.com>
Date: Fri, 3 Mar 2023 21:58:33 -0500
Subject: [PATCH] bgpd: Fix use beyond end of stream of labeled unicast parsing
Fixes a couple crashes associated with attempting to read
beyond the end of the stream.
Reported-by: Iggy Frankovic <iggyfran@amazon.com>
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
---
bgpd/bgp_label.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c
index 0cad119af101..c4a5277553ba 100644
--- a/bgpd/bgp_label.c
+++ b/bgpd/bgp_label.c
@@ -297,6 +297,9 @@ static int bgp_nlri_get_labels(struct peer *peer, uint8_t *pnt, uint8_t plen,
uint8_t llen = 0;
uint8_t label_depth = 0;
+ if (plen < BGP_LABEL_BYTES)
+ return 0;
+
for (; data < lim; data += BGP_LABEL_BYTES) {
memcpy(label, data, BGP_LABEL_BYTES);
llen += BGP_LABEL_BYTES;
@@ -359,6 +362,9 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
addpath_id = ntohl(addpath_id);
pnt += BGP_ADDPATH_ID_LEN;
+
+ if (pnt >= lim)
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
}
/* Fetch prefix length. */
@@ -377,6 +383,15 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
/* Fill in the labels */
llen = bgp_nlri_get_labels(peer, pnt, psize, &label);
+ if (llen == 0) {
+ flog_err(
+ EC_BGP_UPDATE_RCV,
+ "%s [Error] Update packet error (wrong label length 0)",
+ peer->host);
+ bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_INVAL_NETWORK);
+ return BGP_NLRI_PARSE_ERROR_LABEL_LENGTH;
+ }
p.prefixlen = prefixlen - BSIZE(llen);
/* There needs to be at least one label */

View File

@ -0,0 +1,89 @@
From c37119df45bbf4ef713bc10475af2ee06e12f3bf Mon Sep 17 00:00:00 2001
From: Donatas Abraitis <donatas@opensourcerouting.org>
Date: Sun, 29 Oct 2023 22:44:45 +0200
Subject: [PATCH] bgpd: Ignore handling NLRIs if we received MP_UNREACH_NLRI
If we receive MP_UNREACH_NLRI, we should stop handling remaining NLRIs if
no mandatory path attributes received.
In other words, if MP_UNREACH_NLRI received, the remaining NLRIs should be handled
as a new data, but without mandatory attributes, it's a malformed packet.
In normal case, this MUST not happen at all, but to avoid crashing bgpd, we MUST
handle that.
Reported-by: Iggy Frankovic <iggyfran@amazon.com>
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
---
bgpd/bgp_attr.c | 19 ++++++++++---------
bgpd/bgp_attr.h | 1 +
bgpd/bgp_packet.c | 7 ++++++-
3 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 1473dc772502..75aa2ac7cce6 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -3399,15 +3399,6 @@ static int bgp_attr_check(struct peer *peer, struct attr *attr,
if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
return BGP_ATTR_PARSE_PROCEED;
- /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
- to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
- are present, it should. Check for any other attribute being present
- instead.
- */
- if ((!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) &&
- CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI))))
- return BGP_ATTR_PARSE_PROCEED;
-
if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)))
type = BGP_ATTR_ORIGIN;
@@ -3426,6 +3417,16 @@ static int bgp_attr_check(struct peer *peer, struct attr *attr,
&& !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))
type = BGP_ATTR_LOCAL_PREF;
+ /* An UPDATE message that contains the MP_UNREACH_NLRI is not required
+ * to carry any other path attributes. Though if MP_REACH_NLRI or NLRI
+ * are present, it should. Check for any other attribute being present
+ * instead.
+ */
+ if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) &&
+ CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI)))
+ return type ? BGP_ATTR_PARSE_MISSING_MANDATORY
+ : BGP_ATTR_PARSE_PROCEED;
+
/* If any of the well-known mandatory attributes are not present
* in an UPDATE message, then "treat-as-withdraw" MUST be used.
*/
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index fc347e7a1b4b..d30155e6dba0 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -364,6 +364,7 @@ enum bgp_attr_parse_ret {
*/
BGP_ATTR_PARSE_ERROR_NOTIFYPLS = -3,
BGP_ATTR_PARSE_EOR = -4,
+ BGP_ATTR_PARSE_MISSING_MANDATORY = -4,
} bgp_attr_parse_ret_t;
struct bpacket_attr_vec_arr;
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index a7514a26aa64..5dc35157ebf6 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -2359,7 +2359,12 @@ static int bgp_update_receive(struct peer_connection *connection,
/* Network Layer Reachability Information. */
update_len = end - stream_pnt(s);
- if (update_len) {
+ /* If we received MP_UNREACH_NLRI attribute, but also NLRIs, then
+ * NLRIs should be handled as a new data. Though, if we received
+ * NLRIs without mandatory attributes, they should be ignored.
+ */
+ if (update_len && attribute_len &&
+ attr_parse_ret != BGP_ATTR_PARSE_MISSING_MANDATORY) {
/* Set NLRI portion to structure. */
nlris[NLRI_UPDATE].afi = AFI_IP;
nlris[NLRI_UPDATE].safi = SAFI_UNICAST;

View File

@ -0,0 +1,105 @@
From 6814f2e0138a6ea5e1f83bdd9085d9a77999900b Mon Sep 17 00:00:00 2001
From: Donatas Abraitis <donatas@opensourcerouting.org>
Date: Fri, 27 Oct 2023 11:56:45 +0300
Subject: [PATCH] bgpd: Treat EOR as withdrawn to avoid unwanted handling of
malformed attrs
Treat-as-withdraw, otherwise if we just ignore it, we will pass it to be
processed as a normal UPDATE without mandatory attributes, that could lead
to harmful behavior. In this case, a crash for route-maps with the configuration
such as:
```
router bgp 65001
no bgp ebgp-requires-policy
neighbor 127.0.0.1 remote-as external
neighbor 127.0.0.1 passive
neighbor 127.0.0.1 ebgp-multihop
neighbor 127.0.0.1 disable-connected-check
neighbor 127.0.0.1 update-source 127.0.0.2
neighbor 127.0.0.1 timers 3 90
neighbor 127.0.0.1 timers connect 1
!
address-family ipv4 unicast
neighbor 127.0.0.1 addpath-tx-all-paths
neighbor 127.0.0.1 default-originate
neighbor 127.0.0.1 route-map RM_IN in
exit-address-family
exit
!
route-map RM_IN permit 10
set as-path prepend 200
exit
```
Send a malformed optional transitive attribute:
```
import socket
import time
OPEN = (b"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
b"\xff\xff\x00\x62\x01\x04\xfd\xea\x00\x5a\x0a\x00\x00\x01\x45\x02"
b"\x06\x01\x04\x00\x01\x00\x01\x02\x02\x02\x00\x02\x02\x46\x00\x02"
b"\x06\x41\x04\x00\x00\xfd\xea\x02\x02\x06\x00\x02\x06\x45\x04\x00"
b"\x01\x01\x03\x02\x0e\x49\x0c\x0a\x64\x6f\x6e\x61\x74\x61\x73\x2d"
b"\x70\x63\x00\x02\x04\x40\x02\x00\x78\x02\x09\x47\x07\x00\x01\x01"
b"\x80\x00\x00\x00")
KEEPALIVE = (b"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
b"\xff\xff\xff\xff\xff\xff\x00\x13\x04")
UPDATE = bytearray.fromhex("ffffffffffffffffffffffffffffffff002b0200000003c0ff00010100eb00ac100b0b001ad908ac100b0b")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.2', 179))
s.send(OPEN)
data = s.recv(1024)
s.send(KEEPALIVE)
data = s.recv(1024)
s.send(UPDATE)
data = s.recv(1024)
time.sleep(100)
s.close()
```
Reported-by: Iggy Frankovic <iggyfran@amazon.com>
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
---
bgpd/bgp_attr.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index cf2dbe65b805..1473dc772502 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -3391,9 +3391,12 @@ static int bgp_attr_check(struct peer *peer, struct attr *attr,
uint8_t type = 0;
/* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
- * empty UPDATE. */
+ * empty UPDATE. Treat-as-withdraw, otherwise if we just ignore it,
+ * we will pass it to be processed as a normal UPDATE without mandatory
+ * attributes, that could lead to harmful behavior.
+ */
if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
- return BGP_ATTR_PARSE_PROCEED;
+ return BGP_ATTR_PARSE_WITHDRAW;
if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)))
type = BGP_ATTR_ORIGIN;
@@ -3273,7 +3276,13 @@ done:
aspath_unintern(&as4_path);
}
- if (ret != BGP_ATTR_PARSE_ERROR) {
+ /* If we received an UPDATE with mandatory attributes, then
+ * the unrecognized transitive optional attribute of that
+ * path MUST be passed. Otherwise, it's an error, and from
+ * security perspective it might be very harmful if we continue
+ * here with the unrecognized attributes.
+ */
+ if (ret == BGP_ATTR_PARSE_PROCEED) {
/* Finally intern unknown attribute. */
if (attr->transit)
attr->transit = transit_intern(attr->transit);

View File

@ -0,0 +1,47 @@
From 4fc5dafd1c8167a98e3a5f51efc1ea5092513364 Mon Sep 17 00:00:00 2001
From: rgirada <rgirada@vmware.com>
Date: Thu, 18 Feb 2021 20:15:40 -0800
Subject: [PATCH] lib: Routemap is not getting applied upon changing the
routemap action
Description:
This looks broken after NB changes in routemap. When routemap
action modified from permit to deny, it is expected to apply
the new action on the filtered routes before the action in the
routemap data structure has been changed. But currently this is
not handled by the corresponding northbound API.
Signed-off-by: Rajesh Girada <rgirada@vmware.com>
---
lib/routemap_northbound.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/lib/routemap_northbound.c b/lib/routemap_northbound.c
index db06e9caac75..3473ca2aea8c 100644
--- a/lib/routemap_northbound.c
+++ b/lib/routemap_northbound.c
@@ -271,6 +271,7 @@ lib_route_map_entry_description_destroy(struct nb_cb_destroy_args *args)
static int lib_route_map_entry_action_modify(struct nb_cb_modify_args *args)
{
struct route_map_index *rmi;
+ struct route_map *map;
switch (args->event) {
case NB_EV_VALIDATE:
@@ -281,7 +282,15 @@ static int lib_route_map_entry_action_modify(struct nb_cb_modify_args *args)
case NB_EV_APPLY:
rmi = nb_running_get_entry(args->dnode, NULL, true);
rmi->type = yang_dnode_get_enum(args->dnode, NULL);
- /* TODO: notify? */
+ map = rmi->map;
+
+ /* Execute event hook. */
+ if (route_map_master.event_hook) {
+ (*route_map_master.event_hook)(map->name);
+ route_map_notify_dependencies(map->name,
+ RMAP_EVENT_CALL_ADDED);
+ }
+
break;
}

View File

@ -0,0 +1,76 @@
From b08afc81c60607a4f736f418f2e3eb06087f1a35 Mon Sep 17 00:00:00 2001
From: Donatas Abraitis <donatas@opensourcerouting.org>
Date: Fri, 20 Oct 2023 17:49:18 +0300
Subject: [PATCH] bgpd: Handle MP_REACH_NLRI malformed packets with session
reset
Avoid crashing bgpd.
Reported-by: Iggy Frankovic <iggyfran@amazon.com>
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
---
bgpd/bgp_attr.c | 6 +-----
bgpd/bgp_attr.h | 1 -
bgpd/bgp_packet.c | 6 +-----
3 files changed, 2 insertions(+), 11 deletions(-)
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 6925aff727e2..e7bb42a5d989 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -2421,7 +2421,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
mp_update->afi = afi;
mp_update->safi = safi;
- return BGP_ATTR_PARSE_EOR;
+ return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_ATTR, 0);
}
mp_update->afi = afi;
@@ -3759,10 +3759,6 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
goto done;
}
- if (ret == BGP_ATTR_PARSE_EOR) {
- goto done;
- }
-
if (ret == BGP_ATTR_PARSE_ERROR) {
flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR,
"%s: Attribute %s, parse error", peer->host,
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 961e5f122470..fc347e7a1b4b 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -364,7 +364,6 @@ enum bgp_attr_parse_ret {
/* only used internally, send notify + convert to BGP_ATTR_PARSE_ERROR
*/
BGP_ATTR_PARSE_ERROR_NOTIFYPLS = -3,
- BGP_ATTR_PARSE_EOR = -4,
BGP_ATTR_PARSE_MISSING_MANDATORY = -4,
} bgp_attr_parse_ret_t;
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index b585591e2f69..5ecf343b6657 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -2397,8 +2397,7 @@ static int bgp_update_receive(struct peer_connection *connection,
* Non-MP IPv4/Unicast EoR is a completely empty UPDATE
* and MP EoR should have only an empty MP_UNREACH
*/
- if ((!update_len && !withdraw_len && nlris[NLRI_MP_UPDATE].length == 0)
- || (attr_parse_ret == BGP_ATTR_PARSE_EOR)) {
+ if (!update_len && !withdraw_len && nlris[NLRI_MP_UPDATE].length == 0) {
afi_t afi = 0;
safi_t safi;
struct graceful_restart_info *gr_info;
@@ -2419,9 +2418,6 @@ static int bgp_update_receive(struct peer_connection *connection,
&& nlris[NLRI_MP_WITHDRAW].length == 0) {
afi = nlris[NLRI_MP_WITHDRAW].afi;
safi = nlris[NLRI_MP_WITHDRAW].safi;
- } else if (attr_parse_ret == BGP_ATTR_PARSE_EOR) {
- afi = nlris[NLRI_MP_UPDATE].afi;
- safi = nlris[NLRI_MP_UPDATE].safi;
}
if (afi && peer->afc[afi][safi]) {

View File

@ -0,0 +1,60 @@
From d8482bf011cb2b173e85b65b4bf3d5061250cdb9 Mon Sep 17 00:00:00 2001
From: Donatas Abraitis <donatas@opensourcerouting.org>
Date: Mon, 23 Oct 2023 23:34:10 +0300
Subject: [PATCH] bgpd: Check mandatory attributes more carefully for UPDATE
message
If we send a crafted BGP UPDATE message without mandatory attributes, we do
not check if the length of the path attributes is zero or not. We only check
if attr->flag is at least set or not. Imagine we send only unknown transit
attribute, then attr->flag is always 0. Also, this is true only if graceful-restart
capability is received.
Reported-by: Iggy Frankovic <iggyfran@amazon.com>
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
---
bgpd/bgp_attr.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 26fd3de..bcc4424 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -3400,7 +3400,8 @@ bgp_attr_unknown(struct bgp_attr_parser_args *args)
}
/* Well-known attribute check. */
-static int bgp_attr_check(struct peer *peer, struct attr *attr)
+static int bgp_attr_check(struct peer *peer, struct attr *attr,
+ bgp_size_t length)
{
uint8_t type = 0;
@@ -3409,7 +3410,8 @@ static int bgp_attr_check(struct peer *peer, struct attr *attr)
* we will pass it to be processed as a normal UPDATE without mandatory
* attributes, that could lead to harmful behavior.
*/
- if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
+ if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag &&
+ !length)
return BGP_ATTR_PARSE_WITHDRAW;
if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)))
@@ -3462,7 +3464,7 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
bgp_attr_parse_ret_t ret;
uint8_t flag = 0;
uint8_t type = 0;
- bgp_size_t length;
+ bgp_size_t length = 0;
uint8_t *startp, *endp;
uint8_t *attr_endp;
uint8_t seen[BGP_ATTR_BITMAP_SIZE];
@@ -3216,7 +3218,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
}
/* Check all mandatory well-known attributes are present */
- if ((ret = bgp_attr_check(peer, attr)) < 0)
+ if ((ret = bgp_attr_check(peer, attr, length)) < 0)
goto done;
/*

View File

@ -0,0 +1,150 @@
From 06431bfa7570f169637ebb5898f0b0cc3b010802 Mon Sep 17 00:00:00 2001
From: Donald Sharp <sharpd@nvidia.com>
Date: Tue, 6 Dec 2022 10:23:11 -0500
Subject: [PATCH] bgpd: Ensure stream received has enough data
BGP_PREFIX_SID_SRV6_L3_SERVICE attributes must not
fully trust the length value specified in the nlri.
Always ensure that the amount of data we need to read
can be fullfilled.
Reported-by: Iggy Frankovic <iggyfran@amazon.com>
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
---
bgpd/bgp_attr.c | 79 ++++++++++++++++---------------------------------
1 file changed, 25 insertions(+), 54 deletions(-)
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index c35e45275c9b..5b06bc391375 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -2927,9 +2927,21 @@ bgp_attr_psid_sub(uint8_t type, uint16_t length,
uint16_t endpoint_behavior;
char buf[BUFSIZ];
+ /*
+ * Check that we actually have at least as much data as
+ * specified by the length field
+ */
+ if (STREAM_READABLE(peer->curr) < length) {
+ flog_err(
+ EC_BGP_ATTR_LEN,
+ "Prefix SID specifies length %hu, but only %zu bytes remain",
+ length, STREAM_READABLE(peer->curr));
+ return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ args->total);
+ }
+
if (type == BGP_PREFIX_SID_LABEL_INDEX) {
- if (STREAM_READABLE(peer->curr) < length
- || length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
+ if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
flog_err(EC_BGP_ATTR_LEN,
"Prefix SID label index length is %hu instead of %u",
length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
@@ -2951,12 +2963,8 @@ bgp_attr_psid_sub(uint8_t type, uint16_t length,
/* Store label index; subsequently, we'll check on
* address-family */
attr->label_index = label_index;
- }
-
- /* Placeholder code for the IPv6 SID type */
- else if (type == BGP_PREFIX_SID_IPV6) {
- if (STREAM_READABLE(peer->curr) < length
- || length != BGP_PREFIX_SID_IPV6_LENGTH) {
+ } else if (type == BGP_PREFIX_SID_IPV6) {
+ if (length != BGP_PREFIX_SID_IPV6_LENGTH) {
flog_err(EC_BGP_ATTR_LEN,
"Prefix SID IPv6 length is %hu instead of %u",
length, BGP_PREFIX_SID_IPV6_LENGTH);
@@ -2970,10 +2978,7 @@ bgp_attr_psid_sub(uint8_t type, uint16_t length,
stream_getw(peer->curr);
stream_get(&ipv6_sid, peer->curr, 16);
- }
-
- /* Placeholder code for the Originator SRGB type */
- else if (type == BGP_PREFIX_SID_ORIGINATOR_SRGB) {
+ } else if (type == BGP_PREFIX_SID_ORIGINATOR_SRGB) {
/*
* ietf-idr-bgp-prefix-sid-05:
* Length is the total length of the value portion of the
@@ -2998,19 +3003,6 @@ bgp_attr_psid_sub(uint8_t type, uint16_t length,
args->total);
}
- /*
- * Check that we actually have at least as much data as
- * specified by the length field
- */
- if (STREAM_READABLE(peer->curr) < length) {
- flog_err(EC_BGP_ATTR_LEN,
- "Prefix SID Originator SRGB specifies length %hu, but only %zu bytes remain",
- length, STREAM_READABLE(peer->curr));
- return bgp_attr_malformed(
- args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- args->total);
- }
-
/*
* Check that the portion of the TLV containing the sequence of
* SRGBs corresponds to a multiple of the SRGB size; to get
@@ -3034,12 +3026,8 @@ bgp_attr_psid_sub(uint8_t type, uint16_t length,
stream_get(&srgb_base, peer->curr, 3);
stream_get(&srgb_range, peer->curr, 3);
}
- }
-
- /* Placeholder code for the VPN-SID Service type */
- else if (type == BGP_PREFIX_SID_VPN_SID) {
- if (STREAM_READABLE(peer->curr) < length
- || length != BGP_PREFIX_SID_VPN_SID_LENGTH) {
+ } else if (type == BGP_PREFIX_SID_VPN_SID) {
+ if (length != BGP_PREFIX_SID_VPN_SID_LENGTH) {
flog_err(EC_BGP_ATTR_LEN,
"Prefix SID VPN SID length is %hu instead of %u",
length, BGP_PREFIX_SID_VPN_SID_LENGTH);
@@ -2601,18 +2589,13 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length,
sizeof(struct bgp_attr_srv6_vpn));
attr->srv6_vpn->sid_flags = sid_flags;
sid_copy(&attr->srv6_vpn->sid, &ipv6_sid);
- }
-
- /* Placeholder code for the SRv6 L3 Service type */
- else if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE) {
- if (STREAM_READABLE(peer->curr) < length
- || length != BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH) {
- flog_err(EC_BGP_ATTR_LEN,
- "Prefix SID SRv6 L3-Service length is %hu instead of %u",
- length, BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH);
- return bgp_attr_malformed(args,
- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- args->total);
+ } else if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE) {
+ if (STREAM_READABLE(peer->curr) < 1) {
+ flog_err(EC_BGP_ATTR_LEN,
+ "Prefix SID SRV6 L3 Service not enough data left, it must be at least 1 byte");
+ return bgp_attr_malformed(
+ args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ args->total);
}
/* Parse L3-SERVICE Sub-TLV */
@@ -2647,17 +2630,6 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length,
/* Placeholder code for Unsupported TLV */
else {
-
- if (STREAM_READABLE(peer->curr) < length) {
- flog_err(
- EC_BGP_ATTR_LEN,
- "Prefix SID SRv6 length is %hu - too long, only %zu remaining in this UPDATE",
- length, STREAM_READABLE(peer->curr));
- return bgp_attr_malformed(
- args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
- args->total);
- }
-
if (bgp_debug_update(peer, NULL, NULL, 1))
zlog_debug(
"%s attr Prefix-SID sub-type=%u is not supported, skipped",

View File

@ -0,0 +1,34 @@
From cfd04dcb3e689754a72507d086ba3b9709fc5ed8 Mon Sep 17 00:00:00 2001
From: Donald Sharp <sharpd@nvidia.com>
Date: Wed, 5 Apr 2023 14:57:05 -0400
Subject: [PATCH] bgpd: Limit flowspec to no attribute means a implicit
withdrawal
All other parsing functions done from bgp_nlri_parse() assume
no attributes == an implicit withdrawal. Let's move
bgp_nlri_parse_flowspec() into the same alignment.
Reported-by: Matteo Memelli <mmemelli@amazon.it>
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
---
bgpd/bgp_flowspec.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c
index f9debe43cd45..5e1be21402dc 100644
--- a/bgpd/bgp_flowspec.c
+++ b/bgpd/bgp_flowspec.c
@@ -98,6 +98,13 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
afi = packet->afi;
safi = packet->safi;
+ /*
+ * All other AFI/SAFI's treat no attribute as a implicit
+ * withdraw. Flowspec should as well.
+ */
+ if (!attr)
+ withdraw = 1;
+
if (packet->length >= FLOWSPEC_NLRI_SIZELIMIT_EXTENDED) {
flog_err(EC_BGP_FLOWSPEC_PACKET,
"BGP flowspec nlri length maximum reached (%u)",

View File

@ -0,0 +1,267 @@
From 2cf7651f0b1b0123dc5568ebad00ac84a9b3c348 Mon Sep 17 00:00:00 2001
From: Donald Sharp <sharpd@nvidia.com>
Date: Wed, 2 Feb 2022 13:28:42 -0500
Subject: [PATCH] zebra: Make netlink buffer reads resizeable when needed
Currently when the kernel sends netlink messages to FRR
the buffers to receive this data is of fixed length.
The kernel, with certain configurations, will send
netlink messages that are larger than this fixed length.
This leads to situations where, on startup, zebra gets
really confused about the state of the kernel. Effectively
the current algorithm is this:
read up to buffer in size
while (data to parse)
get netlink message header, look at size
parse if you can
The problem is that there is a 32k buffer we read.
We get the first message that is say 1k in size,
subtract that 1k to 31k left to parse. We then
get the next header and notice that the length
of the message is 33k. Which is obviously larger
than what we read in. FRR has no recover mechanism
nor is there a way to know, a priori, what the maximum
size the kernel will send us.
Modify FRR to look at the kernel message and see if the
buffer is large enough, if not, make it large enough to
read in the message.
This code has to be per netlink socket because of the usage
of pthreads. So add to `struct nlsock` the buffer and current
buffer length. Growing it as necessary.
Fixes: #10404
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
---
zebra/kernel_netlink.c | 68 +++++++++++++++++++++++++-----------------
zebra/kernel_netlink.h | 2 +-
zebra/zebra_dplane.c | 4 +++
zebra/zebra_ns.h | 3 ++
4 files changed, 49 insertions(+), 28 deletions(-)
diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h
index ae88f3372b1c..9421ea1c611a 100644
--- a/zebra/kernel_netlink.h
+++ b/zebra/kernel_netlink.h
@@ -96,7 +96,7 @@ extern const char *nl_family_to_str(uint8_t family);
extern const char *nl_rttype_to_str(uint8_t rttype);
extern int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
- const struct nlsock *nl,
+ struct nlsock *nl,
const struct zebra_dplane_info *dp_info,
int count, int startup);
extern int netlink_talk_filter(struct nlmsghdr *h, ns_id_t ns, int startup);
diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h
index 0519e1d5b33d..7a0ffbc1ee6f 100644
--- a/zebra/zebra_ns.h
+++ b/zebra/zebra_ns.h
@@ -39,6 +39,9 @@ struct nlsock {
int seq;
struct sockaddr_nl snl;
char name[64];
+
+ uint8_t *buf;
+ size_t buflen;
};
#endif
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index b8eaeb1..14a40a9 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -90,8 +90,6 @@
*/
#define NL_DEFAULT_BATCH_SEND_THRESHOLD (15 * NL_PKT_BUF_SIZE)
-#define NL_BATCH_RX_BUFSIZE NL_RCV_PKT_BUF_SIZE
-
static const struct message nlmsg_str[] = {{RTM_NEWROUTE, "RTM_NEWROUTE"},
{RTM_DELROUTE, "RTM_DELROUTE"},
{RTM_GETROUTE, "RTM_GETROUTE"},
@@ -164,8 +162,6 @@ DEFINE_MTYPE_STATIC(ZEBRA, NL_BUF, "Zebra Netlink buffers")
size_t nl_batch_tx_bufsize;
char *nl_batch_tx_buf;
-char nl_batch_rx_buf[NL_BATCH_RX_BUFSIZE];
-
_Atomic uint32_t nl_batch_bufsize = NL_DEFAULT_BATCH_BUFSIZE;
_Atomic uint32_t nl_batch_send_threshold = NL_DEFAULT_BATCH_SEND_THRESHOLD;
@@ -322,6 +318,9 @@ static int netlink_socket(struct nlsock *nl, unsigned long groups,
nl->snl = snl;
nl->sock = sock;
+ nl->buflen = NL_RCV_PKT_BUF_SIZE;
+ nl->buf = XMALLOC(MTYPE_NL_BUF, nl->buflen);
+
return ret;
}
@@ -729,19 +728,29 @@ static ssize_t netlink_send_msg(const struct nlsock *nl, void *buf,
*
* Returns -1 on error, 0 if read would block or the number of bytes received.
*/
-static int netlink_recv_msg(const struct nlsock *nl, struct msghdr msg,
- void *buf, size_t buflen)
+static int netlink_recv_msg(struct nlsock *nl, struct msghdr *msg)
{
struct iovec iov;
int status;
- iov.iov_base = buf;
- iov.iov_len = buflen;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
+ iov.iov_base = nl->buf;
+ iov.iov_len = nl->buflen;
+ msg->msg_iov = &iov;
+ msg->msg_iovlen = 1;
do {
- status = recvmsg(nl->sock, &msg, 0);
+ int bytes;
+
+ bytes = recv(nl->sock, NULL, 0, MSG_PEEK | MSG_TRUNC);
+
+ if (bytes >= 0 && (size_t)bytes > nl->buflen) {
+ nl->buf = XREALLOC(MTYPE_NL_BUF, nl->buf, bytes);
+ nl->buflen = bytes;
+ iov.iov_base = nl->buf;
+ iov.iov_len = nl->buflen;
+ }
+
+ status = recvmsg(nl->sock, msg, 0);
} while (status == -1 && errno == EINTR);
if (status == -1) {
@@ -761,10 +770,10 @@ static int netlink_recv_msg(const struct nlsock *nl, struct msghdr msg,
return -1;
}
- if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
+ if (msg->msg_namelen != sizeof(struct sockaddr_nl)) {
flog_err(EC_ZEBRA_NETLINK_LENGTH_ERROR,
"%s sender address length error: length %d", nl->name,
- msg.msg_namelen);
+ msg->msg_namelen);
return -1;
}
@@ -873,8 +882,7 @@ static int netlink_parse_error(const struct nlsock *nl, struct nlmsghdr *h,
* the filter.
*/
int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
- const struct nlsock *nl,
- const struct zebra_dplane_info *zns,
+ struct nlsock *nl, const struct zebra_dplane_info *zns,
int count, int startup)
{
int status;
@@ -883,7 +891,6 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
int read_in = 0;
while (1) {
- char buf[NL_RCV_PKT_BUF_SIZE];
struct sockaddr_nl snl;
struct msghdr msg = {.msg_name = (void *)&snl,
.msg_namelen = sizeof(snl)};
@@ -892,14 +899,14 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
if (count && read_in >= count)
return 0;
- status = netlink_recv_msg(nl, msg, buf, sizeof(buf));
+ status = netlink_recv_msg(nl, &msg);
if (status == -1)
return -1;
else if (status == 0)
break;
read_in++;
- for (h = (struct nlmsghdr *)buf;
+ for (h = (struct nlmsghdr *)nl->buf;
(status >= 0 && NLMSG_OK(h, (unsigned int)status));
h = NLMSG_NEXT(h, status)) {
/* Finish of reading. */
@@ -976,10 +983,10 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
*/
static int
netlink_talk_info(int (*filter)(struct nlmsghdr *, ns_id_t, int startup),
- struct nlmsghdr *n, const struct zebra_dplane_info *dp_info,
+ struct nlmsghdr *n, struct zebra_dplane_info *dp_info,
int startup)
{
- const struct nlsock *nl;
+ struct nlsock *nl;
nl = &(dp_info->nls);
n->nlmsg_seq = nl->seq;
@@ -1067,12 +1074,11 @@ static int nl_batch_read_resp(struct nl_batch *bth)
* message at a time.
*/
while (true) {
- status = netlink_recv_msg(nl, msg, nl_batch_rx_buf,
- sizeof(nl_batch_rx_buf));
+ status = netlink_recv_msg(nl, &msg);
if (status == -1 || status == 0)
return status;
- h = (struct nlmsghdr *)nl_batch_rx_buf;
+ h = (struct nlmsghdr *)nl->buf;
ignore_msg = false;
seq = h->nlmsg_seq;
/*
@@ -1506,11 +1512,15 @@ void kernel_terminate(struct zebra_ns *zns, bool complete)
if (zns->netlink.sock >= 0) {
close(zns->netlink.sock);
zns->netlink.sock = -1;
+ XFREE(MTYPE_NL_BUF, zns->netlink.buf);
+ zns->netlink.buflen = 0;
}
if (zns->netlink_cmd.sock >= 0) {
close(zns->netlink_cmd.sock);
zns->netlink_cmd.sock = -1;
+ XFREE(MTYPE_NL_BUF, zns->netlink_cmd.buf);
+ zns->netlink_cmd.buflen = 0;
}
/* During zebra shutdown, we need to leave the dataplane socket
@@ -1520,6 +1530,8 @@ void kernel_terminate(struct zebra_ns *zns, bool complete)
if (zns->netlink_dplane.sock >= 0) {
close(zns->netlink_dplane.sock);
zns->netlink_dplane.sock = -1;
+ XFREE(MTYPE_NL_BUF, zns->netlink_dplane.buf);
+ zns->netlink_dplane.buflen = 0;
}
}
}
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 14a40a9..2b566d4 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -779,7 +779,7 @@ static int netlink_recv_msg(struct nlsock *nl, struct msghdr *msg)
if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) {
zlog_debug("%s: << netlink message dump [recv]", __func__);
- zlog_hexdump(buf, status);
+ zlog_hexdump(nl->buf, status);
}
return status;
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 2b566d4..0564a6b 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -1060,7 +1060,7 @@ static int nl_batch_read_resp(struct nl_batch *bth)
struct sockaddr_nl snl;
struct msghdr msg = {};
int status, seq;
- const struct nlsock *nl;
+ struct nlsock *nl;
struct zebra_dplane_ctx *ctx;
bool ignore_msg;

206
SOURCES/frr.if Normal file
View File

@ -0,0 +1,206 @@
## <summary>policy for frr</summary>
########################################
## <summary>
## Execute frr_exec_t in the frr domain.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed to transition.
## </summary>
## </param>
#
interface(`frr_domtrans',`
gen_require(`
type frr_t, frr_exec_t;
')
corecmd_search_bin($1)
domtrans_pattern($1, frr_exec_t, frr_t)
')
######################################
## <summary>
## Execute frr in the caller domain.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
interface(`frr_exec',`
gen_require(`
type frr_exec_t;
')
corecmd_search_bin($1)
can_exec($1, frr_exec_t)
')
########################################
## <summary>
## Read frr's log files.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
## <rolecap/>
#
interface(`frr_read_log',`
gen_require(`
type frr_log_t;
')
read_files_pattern($1, frr_log_t, frr_log_t)
optional_policy(`
logging_search_logs($1)
')
')
########################################
## <summary>
## Append to frr log files.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
interface(`frr_append_log',`
gen_require(`
type frr_log_t;
')
append_files_pattern($1, frr_log_t, frr_log_t)
optional_policy(`
logging_search_logs($1)
')
')
########################################
## <summary>
## Manage frr log files
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
interface(`frr_manage_log',`
gen_require(`
type frr_log_t;
')
manage_dirs_pattern($1, frr_log_t, frr_log_t)
manage_files_pattern($1, frr_log_t, frr_log_t)
manage_lnk_files_pattern($1, frr_log_t, frr_log_t)
optional_policy(`
logging_search_logs($1)
')
')
########################################
## <summary>
## Read frr PID files.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
interface(`frr_read_pid_files',`
gen_require(`
type frr_var_run_t;
')
files_search_pids($1)
read_files_pattern($1, frr_var_run_t, frr_var_run_t)
')
########################################
## <summary>
## All of the rules required to administrate
## an frr environment
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
interface(`frr_admin',`
gen_require(`
type frr_t;
type frr_log_t;
type frr_var_run_t;
')
allow $1 frr_t:process { signal_perms };
ps_process_pattern($1, frr_t)
tunable_policy(`deny_ptrace',`',`
allow $1 frr_t:process ptrace;
')
admin_pattern($1, frr_log_t)
files_search_pids($1)
admin_pattern($1, frr_var_run_t)
optional_policy(`
logging_search_logs($1)
')
optional_policy(`
systemd_passwd_agent_exec($1)
systemd_read_fifo_file_passwd_run($1)
')
')
########################################
## <summary>
## Read ifconfig_var_run_t files and link files
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
ifndef(`sysnet_read_ifconfig_run',`
interface(`sysnet_read_ifconfig_run',`
gen_require(`
type ifconfig_var_run_t;
')
manage_files_pattern($1, ifconfig_var_run_t, ifconfig_var_run_t)
list_dirs_pattern($1, ifconfig_var_run_t, ifconfig_var_run_t)
read_files_pattern($1, ifconfig_var_run_t, ifconfig_var_run_t)
read_lnk_files_pattern($1, ifconfig_var_run_t, ifconfig_var_run_t)
')
')
########################################
## <summary>
## Read unconfined_t files and dirs
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
ifndef(`unconfined_read_files',`
interface(`unconfined_read_files',`
gen_require(`
type unconfined_t;
')
allow $1 unconfined_t:file read_file_perms;
allow $1 unconfined_t:dir list_dir_perms;
')
')

View File

@ -31,7 +31,7 @@ files_pid_file(frr_var_run_t)
#
# frr local policy
#
allow frr_t self:capability { fowner fsetid chown dac_override dac_read_search kill net_bind_service net_raw setgid setuid net_admin };
allow frr_t self:capability { fowner fsetid chown dac_override dac_read_search kill net_bind_service net_raw setgid setuid net_admin sys_admin };
allow frr_t self:netlink_route_socket rw_netlink_socket_perms;
allow frr_t self:packet_socket create;
allow frr_t self:process { setcap setpgid };
@ -96,6 +96,7 @@ fs_read_nsfs_files(frr_t)
fs_search_cgroup_dirs(frr_t)
sysnet_exec_ifconfig(frr_t)
sysnet_read_ifconfig_run(frr_t)
userdom_read_admin_home_files(frr_t)
@ -107,6 +108,10 @@ optional_policy(`
logging_send_syslog_msg(frr_t)
')
optional_policy(`
unconfined_read_files(frr_t)
')
optional_policy(`
modutils_exec_kmod(frr_t)
modutils_getattr_module_deps(frr_t)

View File

@ -7,7 +7,7 @@
Name: frr
Version: 7.5.1
Release: 7%{?checkout}%{?dist}
Release: 22%{?checkout}%{?dist}
Summary: Routing daemon
License: GPLv2+
URL: http://www.frrouting.org
@ -53,6 +53,20 @@ Patch0010: 0010-moving-executables.patch
Patch0011: 0011-reload-bfd-profile.patch
Patch0012: 0012-graceful-restart.patch
Patch0013: 0013-CVE-2022-37032.patch
Patch0014: 0014-bfd-profile-crash.patch
Patch0015: 0015-max-ttl-reload.patch
Patch0016: 0016-CVE-2023-38802.patch
Patch0017: 0017-fix-crash-in-plist-update.patch
Patch0018: 0018-CVE-2023-38406.patch
Patch0019: 0019-CVE-2023-38407.patch
Patch0020: 0020-CVE-2023-47234.patch
Patch0021: 0021-CVE-2023-47235.patch
Patch0022: 0022-route-map-event.patch
Patch0023: 0023-CVE-2023-46752.patch
Patch0024: 0024-CVE-2023-46753.patch
Patch0025: 0025-CVE-2023-31490.patch
Patch0026: 0026-CVE-2023-41909.patch
Patch0027: 0027-dynamic-netlink-buffer.patch
%description
FRRouting is free software that manages TCP/IP based routing protocols. It takes
@ -273,6 +287,54 @@ make check PYTHON=%{__python3}
%endif
%changelog
* Wed Feb 07 2024 Michal Ruprich <mruprich@redhat.com> - 7.5.1-22
- Resolves: RHEL-22303 - Zebra not fetching host routes
* Wed Feb 07 2024 Michal Ruprich <mruprich@redhat.com> - 7.5.1-21
- Resolves: RHEL-2216 - NULL pointer dereference
* Wed Feb 07 2024 Michal Ruprich <mruprich@redhat.com> - 7.5.1-20
- Resolves: RHEL-4797 - missing length check in bgp_attr_psid_sub() can lead do DoS
* Mon Feb 05 2024 Michal Ruprich <mruprich@redhat.com> - 7.5.1-19
- Resolves: RHEL-14824 - crafted BGP UPDATE message leading to a crash
* Mon Feb 05 2024 Michal Ruprich <mruprich@redhat.com> - 7.5.1-18
- Resolves: RHEL-14821 - mishandled malformed data leading to a crash
* Tue Dec 19 2023 Michal Ruprich <mruprich@redhat.com> - 7.5.1-17
- Resolves: RHEL-6583 - Routes are not refreshed after changing the inbound route rules from deny to permit
* Tue Dec 19 2023 Michal Ruprich <mruprich@redhat.com> - 7.5.1-16
- Resolves: RHEL-15916 - Flowspec overflow in bgpd/bgp_flowspec.c
- Resolves: RHEL-15919 - Out of bounds read in bgpd/bgp_label.c
- Resolves: RHEL-15869 - crash from specially crafted MP_UNREACH_NLRI-containing BGP UPDATE message
- Resolves: RHEL-15868 - crash from malformed EOR-containing BGP UPDATE message
* Thu Oct 19 2023 Andreas Karis <akaris@redhat.com> - 7.5.1-15
- Resolves: RHEL-12039 - crash in plist update
* Fri Oct 13 2023 Michal Ruprich <mruprich@redhat.com> - 7.5.1-14
- Resolves: RHEL-6617 - Incorrect handling of a error in parsing of an invalid section of a BGP update can de-peer a router
* Tue Oct 10 2023 Michal Ruprich <mruprich@redhat.com> - 7.5.1-13
- Resolves: RHEL-2263 - eBGP multihop peer flapping due to delta miscalculation of new configuration
* Wed Aug 23 2023 Michal Ruprich <mruprich@redhat.com> - 7.5.1-12
- Resolves: #2216911 - Adding missing sys_admin SELinux call
* Mon Aug 21 2023 Michal Ruprich <mruprich@redhat.com> - 7.5.1-11
- Related: #2216911 - Adding unconfined_t type to access namespaces
* Thu Aug 17 2023 Michal Ruprich <mruprich@redhat.com> - 7.5.1-10
- Related: #2226803 - Adding patch
* Wed Aug 16 2023 Michal Ruprich <mruprich@redhat.com> - 7.5.1-9
- Resolves: #2226803 - BFD crash in FRR running in MetalLB
* Fri Aug 11 2023 Michal Ruprich <mruprich@redhat.com> - 7.5.1-8
- Resolves: #2216911 - SELinux is preventing FRR-Zebra to access to network namespaces
* Wed Nov 30 2022 Michal Ruprich <mruprich@redhat.com> - 7.5.1-7
- Resolves: #2128737 - out-of-bounds read in the BGP daemon may lead to information disclosure or denial of service