diff options
author | Ole Troan <ot@cisco.com> | 2021-11-23 15:55:39 +0100 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2021-12-03 09:35:30 +0000 |
commit | 03092c1982468ff6ffe260b0215f910d4c486b04 (patch) | |
tree | 0d58999070b677d38e2aa2f5da4341383beedbb3 /src/vnet/ipsec | |
parent | 2008912b56abbf3167faf9b787df76605684d9e1 (diff) |
ip: extension header parsing fails for fragment header
Refactor and improve boundary checking on IPv6 extension header handling.
Limit parsing of IPv6 extension headers to a maximum of 4 headers and a
depth of 256 bytes.
Type: fix
Signed-off-by: Ole Troan <ot@cisco.com>
Change-Id: Ide40aaa2b482ceef7e92f02fa0caeadb3b8f7556
Signed-off-by: Ole Troan <ot@cisco.com>
Diffstat (limited to 'src/vnet/ipsec')
-rw-r--r-- | src/vnet/ipsec/esp_encrypt.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/src/vnet/ipsec/esp_encrypt.c b/src/vnet/ipsec/esp_encrypt.c index 0d29604e61f..8ac0e1a2be7 100644 --- a/src/vnet/ipsec/esp_encrypt.c +++ b/src/vnet/ipsec/esp_encrypt.c @@ -225,9 +225,8 @@ esp_get_ip6_hdr_len (ip6_header_t * ip6, ip6_ext_header_t ** ext_hdr) return len; } - p = (void *) (ip6 + 1); + p = ip6_next_header (ip6); len += ip6_ext_header_len (p); - while (ext_hdr_is_pre_esp (p->next_hdr)) { len += ip6_ext_header_len (p); @@ -842,16 +841,28 @@ esp_encrypt_inline (vlib_main_t *vm, vlib_node_runtime_t *node, } else /* transport mode */ { - u8 *l2_hdr, l2_len, *ip_hdr, ip_len; + u8 *l2_hdr, l2_len, *ip_hdr; + u16 ip_len; ip6_ext_header_t *ext_hdr; udp_header_t *udp = 0; u16 udp_len = 0; u8 *old_ip_hdr = vlib_buffer_get_current (b[0]); + /* + * Get extension header chain length. It might be longer than the + * buffer's pre_data area. + */ ip_len = (VNET_LINK_IP6 == lt ? esp_get_ip6_hdr_len ((ip6_header_t *) old_ip_hdr, &ext_hdr) : ip4_header_bytes ((ip4_header_t *) old_ip_hdr)); + if ((old_ip_hdr - ip_len) < &b[0]->pre_data[0]) + { + err = ESP_ENCRYPT_ERROR_NO_BUFFERS; + esp_set_next_index (b[0], node, err, n_noop, noop_nexts, + drop_next); + goto trace; + } vlib_buffer_advance (b[0], ip_len); payload = vlib_buffer_get_current (b[0]); |