Version in base suite: 7.5.1-1.1+deb11u1 Base version: frr_7.5.1-1.1+deb11u1 Target version: frr_7.5.1-1.1+deb11u2 Base file: /srv/ftp-master.debian.org/ftp/pool/main/f/frr/frr_7.5.1-1.1+deb11u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/f/frr/frr_7.5.1-1.1+deb11u2.dsc changelog | 15 patches/0001-bgpd-Implement-rfc9072.patch | 559 ++++++++++++++++++++++++++++++ patches/CVE-2022-36440_40302.patch | 62 +++ patches/CVE-2022-40318.patch | 73 +++ patches/CVE-2022-43681.patch | 51 ++ patches/CVE-2023-31490.patch | 150 ++++++++ patches/CVE-2023-38802.patch | 132 +++++++ patches/CVE-2023-41358.patch | 100 +++++ patches/series | 7 9 files changed, 1149 insertions(+) diff -Nru frr-7.5.1/debian/changelog frr-7.5.1/debian/changelog --- frr-7.5.1/debian/changelog 2023-02-24 09:14:19.000000000 +0000 +++ frr-7.5.1/debian/changelog 2023-09-01 04:27:31.000000000 +0000 @@ -1,3 +1,18 @@ +frr (7.5.1-1.1+deb11u2) bullseye-security; urgency=high + + * Non-maintainer upload by the Security Team. + * CVE-2022-36440, CVE-2022-40302, CVE-2022-40318, CVE-2022-43681: + Denial of service with maliciously construct BGP OPEN packet + (Closes: #1035829). + * CVE-2023-31490: Denial of service caused by malformed SRv6 L3 + service attribute (Closes: #1036062). + * CVE-2023-38802: Denial of service caused by corrupted + Tunnel Encapsulation attribute. + * CVE-2023-41358: Denial of service while processing NLRIs with + zero length attribute. + + -- Aron Xu Fri, 01 Sep 2023 12:27:31 +0800 + frr (7.5.1-1.1+deb11u1) bullseye-security; urgency=high * Non-maintainer upload by the Security Team. diff -Nru frr-7.5.1/debian/patches/0001-bgpd-Implement-rfc9072.patch frr-7.5.1/debian/patches/0001-bgpd-Implement-rfc9072.patch --- frr-7.5.1/debian/patches/0001-bgpd-Implement-rfc9072.patch 1970-01-01 00:00:00.000000000 +0000 +++ frr-7.5.1/debian/patches/0001-bgpd-Implement-rfc9072.patch 2023-08-31 12:07:51.000000000 +0000 @@ -0,0 +1,559 @@ +From: https://github.com/FRRouting/frr/commit/d08c0c8077fbb3e100ed2e87927edec1a09d224b +Reviewed-by: Aron Xu + +From d08c0c8077fbb3e100ed2e87927edec1a09d224b Mon Sep 17 00:00:00 2001 +From: Donatas Abraitis +Date: Sat, 20 Nov 2021 22:00:23 +0200 +Subject: [PATCH] bgpd: Implement rfc9072 + +Related: https://datatracker.ietf.org/doc/html/rfc9072 + +Signed-off-by: Donatas Abraitis +--- + bgpd/bgp_open.c | 140 ++++++++++++++++++++++++++++++++-------------- + bgpd/bgp_open.h | 15 ++++- + bgpd/bgp_packet.c | 53 +++++++++++++++--- + bgpd/bgp_vty.c | 47 ++++++++++++++++ + bgpd/bgpd.c | 1 + + bgpd/bgpd.h | 4 ++ + 6 files changed, 207 insertions(+), 53 deletions(-) + +Index: frr-7.5.1/bgpd/bgp_open.c +=================================================================== +--- frr-7.5.1.orig/bgpd/bgp_open.c ++++ frr-7.5.1/bgpd/bgp_open.c +@@ -1016,7 +1016,7 @@ static bool strict_capability_same(struc + /* peek into option, stores ASN to *as4 if the AS4 capability was found. + * Returns 0 if no as4 found, as4cap value otherwise. + */ +-as_t peek_for_as4_capability(struct peer *peer, uint8_t length) ++as_t peek_for_as4_capability(struct peer *peer, uint16_t length) + { + struct stream *s = BGP_INPUT(peer); + size_t orig_getp = stream_get_getp(s); +@@ -1032,7 +1032,7 @@ as_t peek_for_as4_capability(struct peer + */ + while (stream_get_getp(s) < end) { + uint8_t opt_type; +- uint8_t opt_length; ++ uint16_t opt_length; + + /* Check the length. */ + if (stream_get_getp(s) + 2 > end) +@@ -1040,7 +1040,9 @@ as_t peek_for_as4_capability(struct peer + + /* Fetch option type and length. */ + opt_type = stream_getc(s); +- opt_length = stream_getc(s); ++ opt_length = BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer) ++ ? stream_getw(s) ++ : stream_getc(s); + + /* Option length check. */ + if (stream_get_getp(s) + opt_length > end) +@@ -1088,7 +1090,8 @@ end: + * + * @param[out] mp_capability @see bgp_capability_parse() for semantics. + */ +-int bgp_open_option_parse(struct peer *peer, uint8_t length, int *mp_capability) ++int bgp_open_option_parse(struct peer *peer, uint16_t length, ++ int *mp_capability) + { + int ret = 0; + uint8_t *error; +@@ -1107,7 +1110,7 @@ int bgp_open_option_parse(struct peer *p + + while (stream_get_getp(s) < end) { + uint8_t opt_type; +- uint8_t opt_length; ++ uint16_t opt_length; + + /* Must have at least an OPEN option header */ + if (STREAM_READABLE(s) < 2) { +@@ -1119,11 +1122,14 @@ int bgp_open_option_parse(struct peer *p + + /* Fetch option type and length. */ + opt_type = stream_getc(s); +- opt_length = stream_getc(s); ++ opt_length = BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer) ++ ? stream_getw(s) ++ : stream_getc(s); + + /* Option length check. */ + if (STREAM_READABLE(s) < opt_length) { +- zlog_info("%s Option length error", peer->host); ++ zlog_info("%s Option length error (%d)", peer->host, ++ opt_length); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; +@@ -1220,9 +1226,10 @@ int bgp_open_option_parse(struct peer *p + } + + static void bgp_open_capability_orf(struct stream *s, struct peer *peer, +- afi_t afi, safi_t safi, uint8_t code) ++ afi_t afi, safi_t safi, uint8_t code, ++ bool ext_opt_params) + { +- uint8_t cap_len; ++ uint16_t cap_len; + uint8_t orf_len; + unsigned long capp; + unsigned long orfp; +@@ -1236,7 +1243,8 @@ static void bgp_open_capability_orf(stru + + stream_putc(s, BGP_OPEN_OPT_CAP); + capp = stream_get_endp(s); /* Set Capability Len Pointer */ +- stream_putc(s, 0); /* Capability Length */ ++ ext_opt_params ? stream_putw(s, 0) ++ : stream_putc(s, 0); /* Capability Length */ + stream_putc(s, code); /* Capability Code */ + orfp = stream_get_endp(s); /* Set ORF Len Pointer */ + stream_putc(s, 0); /* ORF Length */ +@@ -1284,11 +1292,12 @@ static void bgp_open_capability_orf(stru + + /* Total Capability Len. */ + cap_len = stream_get_endp(s) - capp - 1; +- stream_putc_at(s, capp, cap_len); ++ ext_opt_params ? stream_putw_at(s, capp, cap_len) ++ : stream_putc_at(s, capp, cap_len); + } + + static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer, +- unsigned long cp) ++ bool ext_opt_params) + { + int len; + iana_afi_t pkt_afi; +@@ -1310,7 +1319,8 @@ static void bgp_peer_send_gr_capability( + SET_FLAG(peer->cap, PEER_CAP_RESTART_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + capp = stream_get_endp(s); /* Set Capability Len Pointer */ +- stream_putc(s, 0); /* Capability Length */ ++ ext_opt_params ? stream_putw(s, 0) ++ : stream_putc(s, 0); /* Capability Length */ + stream_putc(s, CAPABILITY_CODE_RESTART); + /* Set Restart Capability Len Pointer */ + rcapp = stream_get_endp(s); +@@ -1365,14 +1375,16 @@ static void bgp_peer_send_gr_capability( + + /* Total Capability Len. */ + len = stream_get_endp(s) - capp - 1; +- stream_putc_at(s, capp, len); ++ ext_opt_params ? stream_putw_at(s, capp, len - 1) ++ : stream_putc_at(s, capp, len); + } + + /* Fill in capability open option to the packet. */ +-void bgp_open_capability(struct stream *s, struct peer *peer) ++uint16_t bgp_open_capability(struct stream *s, struct peer *peer, ++ bool ext_opt_params) + { +- uint8_t len; +- unsigned long cp, capp, rcapp; ++ uint16_t len; ++ unsigned long cp, capp, rcapp, eopl = 0; + iana_afi_t pkt_afi; + afi_t afi; + safi_t safi; +@@ -1381,16 +1393,26 @@ void bgp_open_capability(struct stream * + uint8_t afi_safi_count = 0; + int adv_addpath_tx = 0; + +- /* Remember current pointer for Opt Parm Len. */ ++ /* Non-Ext OP Len. */ + cp = stream_get_endp(s); +- +- /* Opt Parm Len. */ + stream_putc(s, 0); + ++ if (ext_opt_params) { ++ /* Non-Ext OP Len. */ ++ stream_putc_at(s, cp, BGP_OPEN_NON_EXT_OPT_LEN); ++ ++ /* Non-Ext OP Type */ ++ stream_putc(s, BGP_OPEN_NON_EXT_OPT_TYPE_EXTENDED_LENGTH); ++ ++ /* Extended Opt. Parm. Length */ ++ eopl = stream_get_endp(s); ++ stream_putw(s, 0); ++ } ++ + /* Do not send capability. */ + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN) + || CHECK_FLAG(peer->flags, PEER_FLAG_DONT_CAPABILITY)) +- return; ++ return 0; + + /* MP capability for configured AFI, SAFI */ + FOREACH_AFI_SAFI (afi, safi) { +@@ -1401,7 +1423,9 @@ void bgp_open_capability(struct stream * + + peer->afc_adv[afi][safi] = 1; + stream_putc(s, BGP_OPEN_OPT_CAP); +- stream_putc(s, CAPABILITY_CODE_MP_LEN + 2); ++ ext_opt_params ++ ? stream_putw(s, CAPABILITY_CODE_MP_LEN + 2) ++ : stream_putc(s, CAPABILITY_CODE_MP_LEN + 2); + stream_putc(s, CAPABILITY_CODE_MP); + stream_putc(s, CAPABILITY_CODE_MP_LEN); + stream_putw(s, pkt_afi); +@@ -1421,7 +1445,13 @@ void bgp_open_capability(struct stream * + */ + SET_FLAG(peer->cap, PEER_CAP_ENHE_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); +- stream_putc(s, CAPABILITY_CODE_ENHE_LEN + 2); ++ ext_opt_params ++ ? stream_putw(s, ++ CAPABILITY_CODE_ENHE_LEN ++ + 2) ++ : stream_putc(s, ++ CAPABILITY_CODE_ENHE_LEN ++ + 2); + stream_putc(s, CAPABILITY_CODE_ENHE); + stream_putc(s, CAPABILITY_CODE_ENHE_LEN); + +@@ -1442,18 +1472,21 @@ void bgp_open_capability(struct stream * + /* Route refresh. */ + SET_FLAG(peer->cap, PEER_CAP_REFRESH_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); +- stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2); ++ ext_opt_params ? stream_putw(s, CAPABILITY_CODE_REFRESH_LEN + 2) ++ : stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2); + stream_putc(s, CAPABILITY_CODE_REFRESH_OLD); + stream_putc(s, CAPABILITY_CODE_REFRESH_LEN); + stream_putc(s, BGP_OPEN_OPT_CAP); +- stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2); ++ ext_opt_params ? stream_putw(s, CAPABILITY_CODE_REFRESH_LEN + 2) ++ : stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2); + stream_putc(s, CAPABILITY_CODE_REFRESH); + stream_putc(s, CAPABILITY_CODE_REFRESH_LEN); + + /* AS4 */ + SET_FLAG(peer->cap, PEER_CAP_AS4_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); +- stream_putc(s, CAPABILITY_CODE_AS4_LEN + 2); ++ ext_opt_params ? stream_putw(s, CAPABILITY_CODE_AS4_LEN + 2) ++ : stream_putc(s, CAPABILITY_CODE_AS4_LEN + 2); + stream_putc(s, CAPABILITY_CODE_AS4); + stream_putc(s, CAPABILITY_CODE_AS4_LEN); + if (peer->change_local_as) +@@ -1477,7 +1510,11 @@ void bgp_open_capability(struct stream * + + SET_FLAG(peer->cap, PEER_CAP_ADDPATH_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); +- stream_putc(s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count) + 2); ++ ext_opt_params ++ ? stream_putw(s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count) ++ + 2) ++ : stream_putc(s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count) ++ + 2); + stream_putc(s, CAPABILITY_CODE_ADDPATH); + stream_putc(s, CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count); + +@@ -1513,9 +1550,11 @@ void bgp_open_capability(struct stream * + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ORF_PREFIX_RM)) { + bgp_open_capability_orf(s, peer, afi, safi, +- CAPABILITY_CODE_ORF_OLD); ++ CAPABILITY_CODE_ORF_OLD, ++ ext_opt_params); + bgp_open_capability_orf(s, peer, afi, safi, +- CAPABILITY_CODE_ORF); ++ CAPABILITY_CODE_ORF, ++ ext_opt_params); + } + } + +@@ -1523,11 +1562,15 @@ void bgp_open_capability(struct stream * + if (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) { + SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); +- stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2); ++ ext_opt_params ++ ? stream_putw(s, CAPABILITY_CODE_DYNAMIC_LEN + 2) ++ : stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2); + stream_putc(s, CAPABILITY_CODE_DYNAMIC_OLD); + stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN); + stream_putc(s, BGP_OPEN_OPT_CAP); +- stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2); ++ ext_opt_params ++ ? stream_putw(s, CAPABILITY_CODE_DYNAMIC_LEN + 2) ++ : stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2); + stream_putc(s, CAPABILITY_CODE_DYNAMIC); + stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN); + } +@@ -1537,7 +1580,8 @@ void bgp_open_capability(struct stream * + SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + rcapp = stream_get_endp(s); /* Ptr to length placeholder */ +- stream_putc(s, 0); /* dummy len for now */ ++ ext_opt_params ? stream_putw(s, 0) ++ : stream_putc(s, 0); /* Capability Length */ + stream_putc(s, CAPABILITY_CODE_FQDN); + capp = stream_get_endp(s); + stream_putc(s, 0); /* dummy len for now */ +@@ -1559,7 +1603,9 @@ void bgp_open_capability(struct stream * + + /* Set the lengths straight */ + len = stream_get_endp(s) - rcapp - 1; +- stream_putc_at(s, rcapp, len); ++ ext_opt_params ? stream_putw_at(s, rcapp, len - 1) ++ : stream_putc_at(s, rcapp, len); ++ + len = stream_get_endp(s) - capp - 1; + stream_putc_at(s, capp, len); + +@@ -1570,9 +1616,18 @@ void bgp_open_capability(struct stream * + cmd_domainname_get()); + } + +- bgp_peer_send_gr_capability(s, peer, cp); ++ bgp_peer_send_gr_capability(s, peer, ext_opt_params); + + /* Total Opt Parm Len. */ + len = stream_get_endp(s) - cp - 1; + stream_putc_at(s, cp, len); ++ ++ if (ext_opt_params) { ++ len = stream_get_endp(s) - eopl - 2; ++ stream_putw_at(s, eopl, len); ++ } else { ++ stream_putc_at(s, cp, len); ++ } ++ ++ return len; + } +Index: frr-7.5.1/bgpd/bgp_open.h +=================================================================== +--- frr-7.5.1.orig/bgpd/bgp_open.h ++++ frr-7.5.1/bgpd/bgp_open.h +@@ -84,10 +84,19 @@ struct graceful_restart_af { + #define RESTART_R_BIT 0x8000 + #define RESTART_F_BIT 0x80 + +-extern int bgp_open_option_parse(struct peer *, uint8_t, int *); +-extern void bgp_open_capability(struct stream *, struct peer *); ++/* Optional Parameters */ ++#define BGP_OPEN_NON_EXT_OPT_LEN 255 /* Non-Ext OP Len. */ ++#define BGP_OPEN_NON_EXT_OPT_TYPE_EXTENDED_LENGTH 255 /* Non-Ext OP Type */ ++#define BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer) \ ++ (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_OPT_PARAMS) \ ++ || CHECK_FLAG(peer->sflags, PEER_STATUS_EXT_OPT_PARAMS_LENGTH)) ++ ++extern int bgp_open_option_parse(struct peer *peer, uint16_t length, ++ int *mp_capability); ++extern uint16_t bgp_open_capability(struct stream *s, struct peer *peer, ++ bool ext_opt_params); + extern void bgp_capability_vty_out(struct vty *vty, struct peer *peer, + bool use_json, json_object *json_neigh); +-extern as_t peek_for_as4_capability(struct peer *, uint8_t); ++extern as_t peek_for_as4_capability(struct peer *peer, uint16_t length); + + #endif /* _QUAGGA_BGP_OPEN_H */ +Index: frr-7.5.1/bgpd/bgp_packet.c +=================================================================== +--- frr-7.5.1.orig/bgpd/bgp_packet.c ++++ frr-7.5.1/bgpd/bgp_packet.c +@@ -559,8 +559,22 @@ void bgp_open_send(struct peer *peer) + stream_putw(s, send_holdtime); /* Hold Time */ + stream_put_in_addr(s, &peer->local_id); /* BGP Identifier */ + +- /* Set capability code. */ +- bgp_open_capability(s, peer); ++ /* Set capabilities */ ++ if (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_OPT_PARAMS)) { ++ (void)bgp_open_capability(s, peer, true); ++ } else { ++ struct stream *tmp = stream_new(STREAM_SIZE(s)); ++ ++ stream_copy(tmp, s); ++ if (bgp_open_capability(tmp, peer, false) ++ > BGP_OPEN_NON_EXT_OPT_LEN) { ++ stream_free(tmp); ++ (void)bgp_open_capability(s, peer, true); ++ } else { ++ stream_copy(s, tmp); ++ stream_free(tmp); ++ } ++ } + + /* Set BGP packet length. */ + (void)bgp_packet_set_size(s); +@@ -1092,7 +1106,7 @@ static int bgp_open_receive(struct peer + { + int ret; + uint8_t version; +- uint8_t optlen; ++ uint16_t optlen; + uint16_t holdtime; + uint16_t send_holdtime; + as_t remote_as; +@@ -1113,20 +1127,41 @@ static int bgp_open_receive(struct peer + memcpy(notify_data_remote_id, stream_pnt(peer->curr), 4); + remote_id.s_addr = stream_get_ipv4(peer->curr); + +- /* Receive OPEN message log */ +- if (bgp_debug_neighbor_events(peer)) +- zlog_debug( +- "%s rcv OPEN, version %d, remote-as (in open) %u, holdtime %d, id %s", +- peer->host, version, remote_as, holdtime, +- inet_ntoa(remote_id)); + + /* BEGIN to read the capability here, but dont do it yet */ + mp_capability = 0; + optlen = stream_getc(peer->curr); + ++ /* Extended Optional Parameters Length for BGP OPEN Message */ ++ if (optlen == BGP_OPEN_NON_EXT_OPT_LEN ++ || CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_OPT_PARAMS)) { ++ uint8_t opttype; ++ ++ opttype = stream_getc(peer->curr); ++ if (opttype == BGP_OPEN_NON_EXT_OPT_TYPE_EXTENDED_LENGTH) { ++ optlen = stream_getw(peer->curr); ++ SET_FLAG(peer->sflags, ++ PEER_STATUS_EXT_OPT_PARAMS_LENGTH); ++ } ++ } ++ ++ /* Receive OPEN message log */ ++ if (bgp_debug_neighbor_events(peer)) ++ zlog_debug( ++ "%s rcv OPEN%s, version %d, remote-as (in open) %u, holdtime %d, id %pI4", ++ peer->host, ++ CHECK_FLAG(peer->sflags, ++ PEER_STATUS_EXT_OPT_PARAMS_LENGTH) ++ ? " (Extended)" ++ : "", ++ version, remote_as, holdtime, &remote_id); ++ + if (optlen != 0) { + /* If not enough bytes, it is an error. */ + if (STREAM_READABLE(peer->curr) < optlen) { ++ flog_err(EC_BGP_PKT_OPEN, ++ "%s: stream has not enough bytes (%u)", ++ peer->host, optlen); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return BGP_Stop; +Index: frr-7.5.1/bgpd/bgp_vty.c +=================================================================== +--- frr-7.5.1.orig/bgpd/bgp_vty.c ++++ frr-7.5.1/bgpd/bgp_vty.c +@@ -5750,6 +5750,30 @@ DEFUN (no_neighbor_disable_connected_che + PEER_FLAG_DISABLE_CONNECTED_CHECK); + } + ++/* extended-optional-parameters */ ++DEFUN(neighbor_extended_optional_parameters, ++ neighbor_extended_optional_parameters_cmd, ++ "neighbor extended-optional-parameters", ++ NEIGHBOR_STR NEIGHBOR_ADDR_STR2 ++ "Force the extended optional parameters format for OPEN messages\n") ++{ ++ int idx_peer = 1; ++ ++ return peer_flag_set_vty(vty, argv[idx_peer]->arg, ++ PEER_FLAG_EXTENDED_OPT_PARAMS); ++} ++ ++DEFUN(no_neighbor_extended_optional_parameters, ++ no_neighbor_extended_optional_parameters_cmd, ++ "no neighbor extended-optional-parameters", ++ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 ++ "Force the extended optional parameters format for OPEN messages\n") ++{ ++ int idx_peer = 2; ++ ++ return peer_flag_unset_vty(vty, argv[idx_peer]->arg, ++ PEER_FLAG_EXTENDED_OPT_PARAMS); ++} + + /* enforce-first-as */ + DEFUN (neighbor_enforce_first_as, +@@ -11270,6 +11294,14 @@ static void bgp_show_peer(struct vty *vt + "bgpTimerConfiguredKeepAliveIntervalMsecs", + bgp->default_keepalive); + } ++ ++ /* Extended Optional Parameters Length for BGP OPEN Message */ ++ if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(p)) ++ json_object_boolean_true_add( ++ json_neigh, "extendedOptionalParametersLength"); ++ else ++ json_object_boolean_false_add( ++ json_neigh, "extendedOptionalParametersLength"); + } else { + /* Administrative shutdown. */ + if (CHECK_FLAG(p->flags, PEER_FLAG_SHUTDOWN) +@@ -11331,6 +11363,11 @@ static void bgp_show_peer(struct vty *vt + vty_out(vty, ", keepalive interval is %d seconds\n", + bgp->default_keepalive); + } ++ ++ /* Extended Optional Parameters Length for BGP OPEN Message */ ++ if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(p)) ++ vty_out(vty, ++ " Extended Optional Parameters Length is enabled\n"); + } + /* Capability. */ + if (p->status == Established) { +@@ -15047,6 +15084,11 @@ static void bgp_config_write_peer_global + if (peergroup_flag_check(peer, PEER_FLAG_DISABLE_CONNECTED_CHECK)) + vty_out(vty, " neighbor %s disable-connected-check\n", addr); + ++ /* extended-optional-parameters */ ++ if (peergroup_flag_check(peer, PEER_FLAG_EXTENDED_OPT_PARAMS)) ++ vty_out(vty, " neighbor %s extended-optional-parameters\n", ++ addr); ++ + /* enforce-first-as */ + if (peergroup_flag_check(peer, PEER_FLAG_ENFORCE_FIRST_AS)) + vty_out(vty, " neighbor %s enforce-first-as\n", addr); +@@ -16841,6 +16883,11 @@ void bgp_vty_init(void) + install_element(BGP_NODE, &neighbor_disable_connected_check_cmd); + install_element(BGP_NODE, &no_neighbor_disable_connected_check_cmd); + ++ /* "neighbor extended-optional-parameters" commands. */ ++ install_element(BGP_NODE, &neighbor_extended_optional_parameters_cmd); ++ install_element(BGP_NODE, ++ &no_neighbor_extended_optional_parameters_cmd); ++ + /* "neighbor enforce-first-as" commands. */ + install_element(BGP_NODE, &neighbor_enforce_first_as_cmd); + install_element(BGP_NODE, &no_neighbor_enforce_first_as_cmd); +Index: frr-7.5.1/bgpd/bgpd.c +=================================================================== +--- frr-7.5.1.orig/bgpd/bgpd.c ++++ frr-7.5.1/bgpd/bgpd.c +@@ -3910,6 +3910,7 @@ static const struct peer_flag_action pee + {PEER_FLAG_LOCAL_AS_NO_PREPEND, 0, peer_change_none}, + {PEER_FLAG_LOCAL_AS_REPLACE_AS, 0, peer_change_none}, + {PEER_FLAG_UPDATE_SOURCE, 0, peer_change_none}, ++ {PEER_FLAG_EXTENDED_OPT_PARAMS, 0, peer_change_reset}, + {0, 0, 0}}; + + static const struct peer_flag_action peer_af_flag_action_list[] = { +Index: frr-7.5.1/bgpd/bgpd.h +=================================================================== +--- frr-7.5.1.orig/bgpd/bgpd.h ++++ frr-7.5.1/bgpd/bgpd.h +@@ -1166,6 +1166,8 @@ struct peer { + #define PEER_FLAG_GRACEFUL_RESTART (1U << 24) /* Graceful Restart */ + #define PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT (1U << 25) /* Global-Inherit */ + #define PEER_FLAG_RTT_SHUTDOWN (1U << 26) /* shutdown rtt */ ++/* force the extended format for Optional Parameters in OPEN message */ ++#define PEER_FLAG_EXTENDED_OPT_PARAMS (1U << 30) + + /* + *GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART +@@ -1251,6 +1253,8 @@ struct peer { + #define PEER_STATUS_GROUP (1U << 4) /* peer-group conf */ + #define PEER_STATUS_NSF_MODE (1U << 5) /* NSF aware peer */ + #define PEER_STATUS_NSF_WAIT (1U << 6) /* wait comeback peer */ ++/* received extended format encoding for OPEN message */ ++#define PEER_STATUS_EXT_OPT_PARAMS_LENGTH (1U << 7) + + /* Peer status af flags (reset in bgp_stop) */ + uint16_t af_sflags[AFI_MAX][SAFI_MAX]; diff -Nru frr-7.5.1/debian/patches/CVE-2022-36440_40302.patch frr-7.5.1/debian/patches/CVE-2022-36440_40302.patch --- frr-7.5.1/debian/patches/CVE-2022-36440_40302.patch 1970-01-01 00:00:00.000000000 +0000 +++ frr-7.5.1/debian/patches/CVE-2022-36440_40302.patch 2023-08-31 07:55:59.000000000 +0000 @@ -0,0 +1,62 @@ +From 3e46b43e3788f0f87bae56a86b54d412b4710286 Mon Sep 17 00:00:00 2001 +From: Donald Sharp +Date: Fri, 30 Sep 2022 08:51:45 -0400 +Subject: [PATCH] bgpd: Ensure FRR has enough data to read 2 bytes in + peek_for_as4_capability + +In peek_for_as4_capability the code is checking that the +stream has at least 2 bytes to read ( the opt_type and the +opt_length ). However if BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer) +is configured then FRR is reading 3 bytes. Which is not good +since the packet could be badly formated. Ensure that +FRR has the appropriate data length to read the data. + +Signed-off-by: Donald Sharp +--- + bgpd/bgp_open.c | 27 +++++++++++++++++++++------ + 1 file changed, 21 insertions(+), 6 deletions(-) + +diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c +index 7248f034a..a760a7ca0 100644 +--- a/bgpd/bgp_open.c ++++ b/bgpd/bgp_open.c +@@ -1185,15 +1185,30 @@ as_t peek_for_as4_capability(struct peer *peer, uint16_t length) + uint8_t opt_type; + uint16_t opt_length; + +- /* Check the length. */ +- if (stream_get_getp(s) + 2 > end) ++ /* Ensure we can read the option type */ ++ if (stream_get_getp(s) + 1 > end) + goto end; + +- /* Fetch option type and length. */ ++ /* Fetch the option type */ + opt_type = stream_getc(s); +- opt_length = BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer) +- ? stream_getw(s) +- : stream_getc(s); ++ ++ /* ++ * Check the length and fetch the opt_length ++ * If the peer is BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer) ++ * then we do a getw which is 2 bytes. So we need to ++ * ensure that we can read that as well ++ */ ++ if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)) { ++ if (stream_get_getp(s) + 2 > end) ++ goto end; ++ ++ opt_length = stream_getw(s); ++ } else { ++ if (stream_get_getp(s) + 1 > end) ++ goto end; ++ ++ opt_length = stream_getc(s); ++ } + + /* Option length check. */ + if (stream_get_getp(s) + opt_length > end) +-- +2.39.2 + diff -Nru frr-7.5.1/debian/patches/CVE-2022-40318.patch frr-7.5.1/debian/patches/CVE-2022-40318.patch --- frr-7.5.1/debian/patches/CVE-2022-40318.patch 1970-01-01 00:00:00.000000000 +0000 +++ frr-7.5.1/debian/patches/CVE-2022-40318.patch 2023-08-31 08:20:13.000000000 +0000 @@ -0,0 +1,73 @@ +From 1117baca3c592877a4d8a13ed6a1d9bd83977487 Mon Sep 17 00:00:00 2001 +From: Donald Sharp +Date: Fri, 30 Sep 2022 08:57:43 -0400 +Subject: [PATCH] bgpd: Ensure FRR has enough data to read 2 bytes in + bgp_open_option_parse + +In bgp_open_option_parse the code is checking that the +stream has at least 2 bytes to read ( the opt_type and +the opt_length). However if BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer) +is configured then FRR is reading 3 bytes. Which is not good +since the packet could be badly formateed. Ensure that +FRR has the appropriate data length to read the data. + +Signed-off-by: Donald Sharp +--- + bgpd/bgp_open.c | 35 ++++++++++++++++++++++++++++------- + 1 file changed, 28 insertions(+), 7 deletions(-) + +diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c +index a760a7ca0..d1667fac2 100644 +--- a/bgpd/bgp_open.c ++++ b/bgpd/bgp_open.c +@@ -1278,19 +1278,40 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length, + uint8_t opt_type; + uint16_t opt_length; + +- /* Must have at least an OPEN option header */ +- if (STREAM_READABLE(s) < 2) { ++ /* ++ * Check that we can read the opt_type and fetch it ++ */ ++ if (STREAM_READABLE(s) < 1) { + zlog_info("%s Option length error", peer->host); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } +- +- /* Fetch option type and length. */ + opt_type = stream_getc(s); +- opt_length = BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer) +- ? stream_getw(s) +- : stream_getc(s); ++ ++ /* ++ * Check the length of the stream to ensure that ++ * FRR can properly read the opt_length. Then read it ++ */ ++ if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)) { ++ if (STREAM_READABLE(s) < 2) { ++ zlog_info("%s Option length error", peer->host); ++ bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, ++ BGP_NOTIFY_OPEN_MALFORMED_ATTR); ++ return -1; ++ } ++ ++ opt_length = stream_getw(s); ++ } else { ++ if (STREAM_READABLE(s) < 1) { ++ zlog_info("%s Option length error", peer->host); ++ bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, ++ BGP_NOTIFY_OPEN_MALFORMED_ATTR); ++ return -1; ++ } ++ ++ opt_length = stream_getc(s); ++ } + + /* Option length check. */ + if (STREAM_READABLE(s) < opt_length) { +-- +2.39.2 + diff -Nru frr-7.5.1/debian/patches/CVE-2022-43681.patch frr-7.5.1/debian/patches/CVE-2022-43681.patch --- frr-7.5.1/debian/patches/CVE-2022-43681.patch 1970-01-01 00:00:00.000000000 +0000 +++ frr-7.5.1/debian/patches/CVE-2022-43681.patch 2023-08-31 08:21:33.000000000 +0000 @@ -0,0 +1,51 @@ +From 6c4ca9812976596bf8b5226600269fc4031f1422 Mon Sep 17 00:00:00 2001 +From: Donald Sharp +Date: Wed, 2 Nov 2022 13:24:48 -0400 +Subject: [PATCH] bgpd: Ensure that bgp open message stream has enough data to + read + +If a operator receives an invalid packet that is of insufficient size +then it is possible for BGP to assert during reading of the packet +instead of gracefully resetting the connection with the peer. + +Signed-off-by: Donald Sharp +(cherry picked from commit 766eec1b7accffe2c04a5c9ebb14e9f487bb9f78) +--- + bgpd/bgp_packet.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c +index 769f9613d..72d6a9231 100644 +--- a/bgpd/bgp_packet.c ++++ b/bgpd/bgp_packet.c +@@ -1386,8 +1386,27 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size) + || CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_OPT_PARAMS)) { + uint8_t opttype; + ++ if (STREAM_READABLE(peer->curr) < 1) { ++ flog_err( ++ EC_BGP_PKT_OPEN, ++ "%s: stream does not have enough bytes for extended optional parameters", ++ peer->host); ++ bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, ++ BGP_NOTIFY_OPEN_MALFORMED_ATTR); ++ return BGP_Stop; ++ } ++ + opttype = stream_getc(peer->curr); + if (opttype == BGP_OPEN_NON_EXT_OPT_TYPE_EXTENDED_LENGTH) { ++ if (STREAM_READABLE(peer->curr) < 2) { ++ flog_err( ++ EC_BGP_PKT_OPEN, ++ "%s: stream does not have enough bytes to read the extended optional parameters optlen", ++ peer->host); ++ bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, ++ BGP_NOTIFY_OPEN_MALFORMED_ATTR); ++ return BGP_Stop; ++ } + optlen = stream_getw(peer->curr); + SET_FLAG(peer->sflags, + PEER_STATUS_EXT_OPT_PARAMS_LENGTH); +-- +2.39.2 + diff -Nru frr-7.5.1/debian/patches/CVE-2023-31490.patch frr-7.5.1/debian/patches/CVE-2023-31490.patch --- frr-7.5.1/debian/patches/CVE-2023-31490.patch 1970-01-01 00:00:00.000000000 +0000 +++ frr-7.5.1/debian/patches/CVE-2023-31490.patch 2023-08-31 12:08:14.000000000 +0000 @@ -0,0 +1,150 @@ +From: https://github.com/FRRouting/frr/commit/06431bfa7570f169637ebb5898f0b0cc3b010802 +Reviewed-by: Aron Xu + +From 06431bfa7570f169637ebb5898f0b0cc3b010802 Mon Sep 17 00:00:00 2001 +From: Donald Sharp +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 +Signed-off-by: Donald Sharp +--- + bgpd/bgp_attr.c | 79 ++++++++++++++++--------------------------------- + 1 file changed, 25 insertions(+), 54 deletions(-) + +Index: frr-7.5.1/bgpd/bgp_attr.c +=================================================================== +--- frr-7.5.1.orig/bgpd/bgp_attr.c ++++ frr-7.5.1/bgpd/bgp_attr.c +@@ -2464,9 +2464,21 @@ static bgp_attr_parse_ret_t bgp_attr_psi + 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); +@@ -2488,12 +2500,8 @@ static bgp_attr_parse_ret_t bgp_attr_psi + /* 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); +@@ -2507,10 +2515,7 @@ static bgp_attr_parse_ret_t bgp_attr_psi + 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 +@@ -2536,19 +2541,6 @@ static bgp_attr_parse_ret_t bgp_attr_psi + } + + /* +- * 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 + * that length, we skip the 16 bit flags field +@@ -2571,12 +2563,8 @@ static bgp_attr_parse_ret_t bgp_attr_psi + 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); +@@ -2611,17 +2599,12 @@ static bgp_attr_parse_ret_t bgp_attr_psi + 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) { ++ } 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 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, ++ "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); + } + +@@ -2657,17 +2640,6 @@ static bgp_attr_parse_ret_t bgp_attr_psi + + /* 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", diff -Nru frr-7.5.1/debian/patches/CVE-2023-38802.patch frr-7.5.1/debian/patches/CVE-2023-38802.patch --- frr-7.5.1/debian/patches/CVE-2023-38802.patch 1970-01-01 00:00:00.000000000 +0000 +++ frr-7.5.1/debian/patches/CVE-2023-38802.patch 2023-09-01 04:12:33.000000000 +0000 @@ -0,0 +1,132 @@ +From: https://github.com/FRRouting/frr/commit/76e43eab2f82d24c398d5ba545892c6ce97def87 +Reviewed-by: Aron Xu + +From 46817adab03802355c3cce7b753c7a735bdcc5ae Mon Sep 17 00:00:00 2001 +From: Donatas Abraitis +Date: Thu, 13 Jul 2023 22:32:03 +0300 +Subject: [PATCH 1/2] 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 +(cherry picked from commit bcb6b58d9530173df41d3a3cbc4c600ee0b4b186) +--- + bgpd/bgp_attr.c | 61 ++++++++++++++++++++----------------------------- + 1 file changed, 25 insertions(+), 36 deletions(-) + +Index: frr-7.5.1/bgpd/bgp_attr.c +=================================================================== +--- frr-7.5.1.orig/bgpd/bgp_attr.c ++++ frr-7.5.1/bgpd/bgp_attr.c +@@ -1225,6 +1225,7 @@ bgp_attr_malformed(struct bgp_attr_parse + 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: +@@ -2320,26 +2321,21 @@ bgp_attr_ipv6_ext_communities(struct bgp + } + + /* 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) { +@@ -2347,12 +2343,11 @@ static int bgp_attr_encap(uint8_t type, + 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)); +@@ -2382,13 +2377,11 @@ static int bgp_attr_encap(uint8_t type, + } + + 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 */ +@@ -2434,13 +2427,10 @@ static int bgp_attr_encap(uint8_t type, + + 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; +@@ -3100,8 +3090,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(stru + 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); diff -Nru frr-7.5.1/debian/patches/CVE-2023-41358.patch frr-7.5.1/debian/patches/CVE-2023-41358.patch --- frr-7.5.1/debian/patches/CVE-2023-41358.patch 1970-01-01 00:00:00.000000000 +0000 +++ frr-7.5.1/debian/patches/CVE-2023-41358.patch 2023-09-01 04:13:10.000000000 +0000 @@ -0,0 +1,100 @@ +From f291f1ee9434f56d4b185db0652794a92e313b00 Mon Sep 17 00:00:00 2001 +From: Donatas Abraitis +Date: Tue, 22 Aug 2023 22:52:04 +0300 +Subject: [PATCH] bgpd: Do not process NLRIs if the attribute length is zero + +``` +3 0x00007f423aa42476 in __GI_raise (sig=sig@entry=11) at ../sysdeps/posix/raise.c:26 +4 0x00007f423aef9740 in core_handler (signo=11, siginfo=0x7fffc414deb0, context=) at lib/sigevent.c:246 +5 +6 0x0000564dea2fc71e in route_set_aspath_prepend (rule=0x564debd66d50, prefix=0x7fffc414ea30, object=0x7fffc414e400) + at bgpd/bgp_routemap.c:2258 +7 0x00007f423aeec7e0 in route_map_apply_ext (map=, prefix=prefix@entry=0x7fffc414ea30, + match_object=match_object@entry=0x7fffc414e400, set_object=set_object@entry=0x7fffc414e400, pref=pref@entry=0x0) at lib/routemap.c:2690 +8 0x0000564dea2d277e in bgp_input_modifier (peer=peer@entry=0x7f4238f59010, p=p@entry=0x7fffc414ea30, attr=attr@entry=0x7fffc414e770, + afi=afi@entry=AFI_IP, safi=safi@entry=SAFI_UNICAST, rmap_name=rmap_name@entry=0x0, label=0x0, num_labels=0, dest=0x564debdd5130) + at bgpd/bgp_route.c:1772 +9 0x0000564dea2df762 in bgp_update (peer=peer@entry=0x7f4238f59010, p=p@entry=0x7fffc414ea30, addpath_id=addpath_id@entry=0, + attr=0x7fffc414eb50, afi=afi@entry=AFI_IP, safi=, safi@entry=SAFI_UNICAST, type=9, sub_type=0, prd=0x0, label=0x0, + num_labels=0, soft_reconfig=0, evpn=0x0) at bgpd/bgp_route.c:4374 +10 0x0000564dea2e2047 in bgp_nlri_parse_ip (peer=0x7f4238f59010, attr=attr@entry=0x7fffc414eb50, packet=0x7fffc414eaf0) + at bgpd/bgp_route.c:6249 +11 0x0000564dea2c5a58 in bgp_nlri_parse (peer=peer@entry=0x7f4238f59010, attr=attr@entry=0x7fffc414eb50, + packet=packet@entry=0x7fffc414eaf0, mp_withdraw=mp_withdraw@entry=false) at bgpd/bgp_packet.c:339 +12 0x0000564dea2c5d66 in bgp_update_receive (peer=peer@entry=0x7f4238f59010, size=size@entry=109) at bgpd/bgp_packet.c:2024 +13 0x0000564dea2c901d in bgp_process_packet (thread=) at bgpd/bgp_packet.c:2933 +14 0x00007f423af0bf71 in event_call (thread=thread@entry=0x7fffc414ee40) at lib/event.c:1995 +15 0x00007f423aebb198 in frr_run (master=0x564deb73c670) at lib/libfrr.c:1213 +16 0x0000564dea261b83 in main (argc=, argv=) at bgpd/bgp_main.c:505 +``` + +With the configuration: + +``` +frr version 9.1-dev-MyOwnFRRVersion +frr defaults traditional +hostname ip-172-31-13-140 +log file /tmp/debug.log +log syslog +service integrated-vtysh-config +! +debug bgp keepalives +debug bgp neighbor-events +debug bgp updates in +debug bgp updates out +! +router bgp 100 + bgp router-id 9.9.9.9 + no bgp ebgp-requires-policy + bgp bestpath aigp + neighbor 172.31.2.47 remote-as 200 + ! + address-family ipv4 unicast + neighbor 172.31.2.47 default-originate + neighbor 172.31.2.47 route-map RM_IN in + exit-address-family +exit +! +route-map RM_IN permit 10 + set as-path prepend 200 +exit +! +``` + +The issue is that we try to process NLRIs even if the attribute length is 0. + +Later bgp_update() will handle route-maps and a crash occurs because all the +attributes are NULL, including aspath, where we dereference. + +According to the RFC 4271: + +A value of 0 indicates that neither the Network Layer + Reachability Information field nor the Path Attribute field is + present in this UPDATE message. + +But with a fuzzed UPDATE message this can be faked. I think it's reasonable +to skip processing NLRIs if both update_len and attribute_len are 0. + +Reported-by: Iggy Frankovic +Signed-off-by: Donatas Abraitis +(cherry picked from commit 28ccc24d38df1d51ed8a563507e5d6f6171fdd38) +--- + bgpd/bgp_packet.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c +index 60f1dcbcd..a02d54894 100644 +--- a/bgpd/bgp_packet.c ++++ b/bgpd/bgp_packet.c +@@ -1983,7 +1983,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size) + /* Network Layer Reachability Information. */ + update_len = end - stream_pnt(s); + +- if (update_len) { ++ if (update_len && attribute_len) { + /* Set NLRI portion to structure. */ + nlris[NLRI_UPDATE].afi = AFI_IP; + nlris[NLRI_UPDATE].safi = SAFI_UNICAST; +-- +2.39.2 + diff -Nru frr-7.5.1/debian/patches/series frr-7.5.1/debian/patches/series --- frr-7.5.1/debian/patches/series 2023-02-24 09:14:19.000000000 +0000 +++ frr-7.5.1/debian/patches/series 2023-09-01 04:22:25.000000000 +0000 @@ -1,2 +1,9 @@ 0001-yang-fix-zebra-module.patch +0001-bgpd-Implement-rfc9072.patch CVE-2022-37032.patch +CVE-2022-36440_40302.patch +CVE-2022-40318.patch +CVE-2022-43681.patch +CVE-2023-31490.patch +CVE-2023-38802.patch +CVE-2023-41358.patch