From 03092c1982468ff6ffe260b0215f910d4c486b04 Mon Sep 17 00:00:00 2001 From: Ole Troan Date: Tue, 23 Nov 2021 15:55:39 +0100 Subject: 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 Change-Id: Ide40aaa2b482ceef7e92f02fa0caeadb3b8f7556 Signed-off-by: Ole Troan --- src/vnet/ipsec/esp_encrypt.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'src/vnet/ipsec/esp_encrypt.c') 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]); -- cgit 1.2.3-korg