diff options
author | Donald Sharp <sharpd@nvidia.com> | 2022-09-30 14:57:43 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@nvidia.com> | 2022-09-30 15:00:02 +0200 |
commit | 1117baca3c592877a4d8a13ed6a1d9bd83977487 (patch) | |
tree | 69f5bb500d282c9a6ddaad9a972a0e86cb16a1bd /bgpd/bgp_open.c | |
parent | bgpd: Ensure FRR has enough data to read 2 bytes in peek_for_as4_capability (diff) | |
download | frr-1117baca3c592877a4d8a13ed6a1d9bd83977487.tar.xz frr-1117baca3c592877a4d8a13ed6a1d9bd83977487.zip |
bgpd: Ensure FRR has enough data to read 2 bytes in bgp_open_option_parse
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>
Diffstat (limited to 'bgpd/bgp_open.c')
-rw-r--r-- | bgpd/bgp_open.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index a760a7ca0..d1667fac2 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -1278,19 +1278,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) { |