| From 72088b05d469a6b6a8b9a2b250885246ea0c2acb Mon Sep 17 00:00:00 2001 |
| From: Donald Sharp <sharpd@nvidia.com> |
| Date: Fri, 30 Sep 2022 08:57:43 -0400 |
| Subject: [PATCH] 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> |
| (cherry picked from commit 1117baca3c592877a4d8a13ed6a1d9bd83977487) |
| |
| CVE: CVE-2022-40318 |
| |
| Upstream-Status: Backport |
| [https://github.com/FRRouting/frr/commit/72088b05d469a6b6a8b9a2b250885246ea0c2acb] |
| |
| Signed-off-by: Jonas Gorski <jonas.gorski@bisdn.de> |
| --- |
| bgpd/bgp_open.c | 35 ++++++++++++++++++++++++++++------- |
| 1 file changed, 28 insertions(+), 7 deletions(-) |
| |
| diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c |
| index fe4c24a8c979..de550d2ac607 100644 |
| --- a/bgpd/bgp_open.c |
| +++ b/bgpd/bgp_open.c |
| @@ -1209,19 +1209,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) { |
| -- |
| 2.40.1 |
| |