]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Ensure FRR has enough data to read 2 bytes in peek_for_as4_capability
authorDonald Sharp <sharpd@nvidia.com>
Fri, 30 Sep 2022 12:51:45 +0000 (08:51 -0400)
committerMergify <37929162+mergify[bot]@users.noreply.github.com>
Fri, 7 Oct 2022 18:37:37 +0000 (18:37 +0000)
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 <sharpd@nvidia.com>
(cherry picked from commit 3e46b43e3788f0f87bae56a86b54d412b4710286)

bgpd/bgp_open.c

index fa3fa3fcee35655f531a24c337414cd6c69bec41..7c1fccc06719c845537608cdb5341f7aa72abfa1 100644 (file)
@@ -1134,15 +1134,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)