diff options
author | Donald Sharp <sharpd@nvidia.com> | 2022-09-30 14:51:45 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@nvidia.com> | 2022-09-30 14:59:52 +0200 |
commit | 3e46b43e3788f0f87bae56a86b54d412b4710286 (patch) | |
tree | 347715f8a7e13602b67de932a3c9e74962e5d46c /bgpd/bgp_open.c | |
parent | Merge pull request #12035 from donaldsharp/pim6_write_non_integrated (diff) | |
download | frr-3e46b43e3788f0f87bae56a86b54d412b4710286.tar.xz frr-3e46b43e3788f0f87bae56a86b54d412b4710286.zip |
bgpd: Ensure FRR has enough data to read 2 bytes in peek_for_as4_capability
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>
Diffstat (limited to 'bgpd/bgp_open.c')
-rw-r--r-- | bgpd/bgp_open.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 7248f034a..a760a7ca0 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -1185,15 +1185,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) |