new file mode 100644
@@ -0,0 +1,160 @@
+From 72c13aac2eb7c8f3a10ad806d80ab635c28f4c04 Mon Sep 17 00:00:00 2001
+From: Narpat Mali <narpat.mali@windriver.com>
+Date: Wed, 21 Jun 2023 15:24:50 +0000
+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>
+
+CVE: CVE-2023-31490
+
+Upstream-Status: Backport [https://github.com/FRRouting/frr/pull/12454/commits/06431bfa7570f169637ebb5898f0b0cc3b010802]
+
+Signed-off-by: Narpat Mali <narpat.mali@windriver.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 2154baf4e..5d06991e2 100644
+--- a/bgpd/bgp_attr.c
++++ b/bgpd/bgp_attr.c
+@@ -2722,9 +2722,21 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length,
+ uint8_t sid_type, sid_flags;
+ 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);
+@@ -2746,12 +2758,8 @@ static bgp_attr_parse_ret_t 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);
+@@ -2765,10 +2773,7 @@ static bgp_attr_parse_ret_t 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
+@@ -2793,19 +2798,6 @@ static bgp_attr_parse_ret_t 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
+@@ -2829,12 +2821,8 @@ static bgp_attr_parse_ret_t 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);
+@@ -2870,39 +2858,22 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length,
+ attr->srv6_vpn->sid_flags = sid_flags;
+ sid_copy(&attr->srv6_vpn->sid, &ipv6_sid);
+ attr->srv6_vpn = srv6_vpn_intern(attr->srv6_vpn);
+- }
+-
+- /* Placeholder code for the SRv6 L3 Service type */
+- else if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE) {
+- if (STREAM_READABLE(peer->curr) < 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, but only %zu bytes remain",
+- length, STREAM_READABLE(peer->curr));
+- return bgp_attr_malformed(args,
+- BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+- args->total);
++ "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);
+ }
+-
+ /* ignore reserved */
+ stream_getc(peer->curr);
+
+ return bgp_attr_srv6_service(args);
+ }
+-
+ /* 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",
+--
+2.40.0
@@ -13,6 +13,7 @@ SRC_URI = "git://github.com/FRRouting/frr.git;protocol=https;branch=stable/8.2 \
file://CVE-2022-37035.patch \
file://CVE-2022-37032.patch \
file://CVE-2022-42917.patch \
+ file://CVE-2023-31490.patch \
file://frr.pam \
"