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

bgpd/bgp_open.c

index 7c1fccc06719c845537608cdb5341f7aa72abfa1..55c83ea0ddf9c1de62e7dddb2b7b9d31c211cada 100644 (file)
@@ -1227,19 +1227,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) {