From 255a9ea63f8e5c2b21ffcfe37d04c155732ad263 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Wed, 27 May 2026 14:51:12 +0300 Subject: [PATCH] bgpd: Avoid cluster list attribute truncation RFC 4271 4.3 says: The fourth high-order bit (bit 3) of the Attribute Flags octet is the Extended Length bit. It defines whether the Attribute Length is one octet (if set to 0) or two octets (if set to 1). The lower-order four bits of the Attribute Flags octet are unused. They MUST be zero when sent and MUST be ignored when received. If the Extended Length bit of the Attribute Flags octet is set to 0, the third octet of the Path Attribute contains the length of the attribute data in octets. If the Extended Length bit of the Attribute Flags octet is set to 1, the third and fourth octets of the path attribute contain the length of the attribute data in octets. Signed-off-by: Donatas Abraitis (cherry picked from commit 9397c360223d3fcc00ed368c04c8e56808ede267) --- bgpd/bgp_attr.c | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 36ca96a55a3f..cd1972e9ae27 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -5243,27 +5243,38 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, struct strea stream_put_in_addr(s, &from->remote_id); /* Cluster list. */ - stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); - stream_putc(s, BGP_ATTR_CLUSTER_LIST); - - if (cluster) { - stream_putc(s, cluster->length + 4); - /* If this peer configuration's parent BGP has - * cluster_id. */ - if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID)) - stream_put_in_addr(s, &bgp->cluster_id); - else - stream_put_in_addr(s, &bgp->router_id); - stream_put(s, cluster->list, cluster->length); + /* RFC 4271 4.3 says: + * The fourth high-order bit (bit 3) of the Attribute Flags octet + * is the Extended Length bit. It defines whether the Attribute + * Length is one octet (if set to 0) or two octets (if set to 1). + * + * If the Extended Length bit of the Attribute Flags octet is set + * to 0, the third octet of the Path Attribute contains the length + * of the attribute data in octets. + * + * If the Extended Length bit of the Attribute Flags octet is set + * to 1, the third and fourth octets of the path attribute contain + * the length of the attribute data in octets. + */ + if (cluster && cluster->length + 4 > 255) { + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN); + stream_putc(s, BGP_ATTR_CLUSTER_LIST); + stream_putw(s, cluster->length + 4); } else { - stream_putc(s, 4); - /* If this peer configuration's parent BGP has - * cluster_id. */ - if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID)) - stream_put_in_addr(s, &bgp->cluster_id); - else - stream_put_in_addr(s, &bgp->router_id); + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); + stream_putc(s, BGP_ATTR_CLUSTER_LIST); + stream_putc(s, cluster ? cluster->length + 4 : 4); } + + /* If this peer configuration's parent BGP has + * cluster_id. */ + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID)) + stream_put_in_addr(s, &bgp->cluster_id); + else + stream_put_in_addr(s, &bgp->router_id); + + if (cluster) + stream_put(s, cluster->list, cluster->length); } /* Extended IPv6/Communities attributes. */