summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_open.c
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@nvidia.com>2022-09-30 14:51:45 +0200
committerDonald Sharp <sharpd@nvidia.com>2022-09-30 14:59:52 +0200
commit3e46b43e3788f0f87bae56a86b54d412b4710286 (patch)
tree347715f8a7e13602b67de932a3c9e74962e5d46c /bgpd/bgp_open.c
parentMerge pull request #12035 from donaldsharp/pim6_write_non_integrated (diff)
downloadfrr-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.c27
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)