summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_open.c
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@nvidia.com>2022-09-30 14:57:43 +0200
committerDonald Sharp <sharpd@nvidia.com>2022-09-30 15:00:02 +0200
commit1117baca3c592877a4d8a13ed6a1d9bd83977487 (patch)
tree69f5bb500d282c9a6ddaad9a972a0e86cb16a1bd /bgpd/bgp_open.c
parentbgpd: Ensure FRR has enough data to read 2 bytes in peek_for_as4_capability (diff)
downloadfrr-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.c35
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) {