]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: Fix lcom->str string length to correctly cover aliases
authorDonald Sharp <sharpd@nvidia.com>
Thu, 20 Apr 2023 20:27:20 +0000 (16:27 -0400)
committerDonatas Abraitis <donatas@opensourcerouting.org>
Fri, 21 Apr 2023 06:32:49 +0000 (09:32 +0300)
If you have a very large number of large communities whose
string length happened to be greater than BUFSIZ FRR's bgpd
would crash.  This is because bgpd would write beyond
the end of the string.

Originally the code auto-calculated the string size appropriately
but commit ed0e57e3f079352714c3a3a8a5b0dddf4aadfe1d modified
the string length to be a hard coded BUFSIZ.  When a route-map
like this is added:

route-map LARGE-OUT permit 10
 set large-community 4635:0:0 4635:1:906 4635:1:2906 4635:1:4515 4635:1:4594 4635:1:4641 4635:1:4760 4635:1:7979 4635:1:9253 4635:1:9293 4635:1:9304 4635:1:9908 4635:1:13335 4635:1:16265 4635:1:17924 4635:1:18013 4635:1:20940 4635:1:22822 4635:1:24429 4635:1:24482 4635:1:32590 4635:1:32934 4635:1:36692 4635:1:38008 4635:1:38819 4635:1:41378 4635:1:45753 4635:1:46489 4635:1:49544 4635:1:51847 4635:1:54574 4635:1:54994 4635:1:55720 4635:1:56059 4635:1:57724 4635:1:65021 4635:1:134823 4635:1:136907 4635:1:146961 24115:0:24115 24115:1:906 24115:1:2906 24115:1:4515 24115:1:4594 24115:1:4641 24115:1:4760 24115:1:7979 24115:1:9253 24115:1:9293 24115:1:9304 24115:1:9908 24115:1:13335 24115:1:16265 24115:1:17924 24115:1:18013 24115:1:20940 24115:1:22822 24115:1:24429 24115:1:24482 24115:1:32590 24115:1:32934 24115:1:36692 24115:1:38008 24115:1:38819 24115:1:41378 24115:1:45753 24115:1:46489 24115:1:49544 24115:1:51847 24115:1:54574 24115:1:54994 24115:1:55720 24115:1:56059 24115:1:57724 24115:1:65021 24115:1:134823 24115:1:136907 24115:1:100000 24115:1:100001 24115:1:100002
exit

BGP would have issues and crash.

Modify the code to correctly determine the string length of the communities
and to also double check if the string has an alias and ensure that the
string is still sufficiently large enough.  If not auto size it again.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
bgpd/bgp_lcommunity.c

index e0cca50d897e9a065ccdd1c5a1b34efa2f45e1e9..223882ba0570ffce03b02e3ab3241da1aa55a4fc 100644 (file)
@@ -211,12 +211,13 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json,
        }
 
        /* 1 space + lcom->size lcom strings + null terminator */
-       size_t str_buf_sz = BUFSIZ;
+       size_t str_buf_sz = (LCOMMUNITY_STRLEN * lcom->size) + 2;
        str_buf = XCALLOC(MTYPE_LCOMMUNITY_STR, str_buf_sz);
 
+       len = 0;
        for (i = 0; i < lcom->size; i++) {
                if (i > 0)
-                       strlcat(str_buf, " ", str_buf_sz);
+                       len = strlcat(str_buf, " ", str_buf_sz);
 
                pnt = lcom->val + (i * LCOMMUNITY_SIZE);
                pnt = ptr_get_be32(pnt, &global);
@@ -229,11 +230,22 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json,
                snprintf(lcsb, sizeof(lcsb), "%u:%u:%u", global, local1,
                         local2);
 
+               /*
+                * Aliases can cause havoc, if the alias length is greater
+                * than the LCOMMUNITY_STRLEN for a particular item
+                * then we need to realloc the memory associated
+                * with the string so that it can fit
+                */
                const char *com2alias =
                        translate_alias ? bgp_community2alias(lcsb) : lcsb;
+               size_t individual_len = strlen(com2alias);
+               if (individual_len + len > str_buf_sz) {
+                       str_buf_sz = individual_len + len + 1;
+                       str_buf = XREALLOC(MTYPE_LCOMMUNITY_STR, str_buf,
+                                          str_buf_sz);
+               }
 
                len = strlcat(str_buf, com2alias, str_buf_sz);
-               assert((unsigned int)len < str_buf_sz);
 
                if (make_json) {
                        json_string = json_object_new_string(com2alias);