summaryrefslogtreecommitdiffstats
path: root/src/vnet/ipsec/esp_encrypt.c
diff options
context:
space:
mode:
authorFilip Tehlar <ftehlar@cisco.com>2019-11-18 22:21:37 +0000
committerDamjan Marion <dmarion@me.com>2019-11-22 12:36:22 +0000
commit8cdb1a0a698e2a51c9151401de4a57cae2d29d48 (patch)
treed94ddb47fdb16b65e3e05f92a2cf289708b4ecf3 /src/vnet/ipsec/esp_encrypt.c
parent595d6f8b7cadfcd7b0a7c3a28b787c476dbebaba (diff)
ipsec: fix trailing data overflow
IPsec writes trailing data at the end of the buffer without checking if there is enough space. If the packet length equals buffer size this leads to rewiting of the next buffer header in the pool. Type: fix Change-Id: Iceb27bb724c7243863a4b532aad0808051b7d74c Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
Diffstat (limited to 'src/vnet/ipsec/esp_encrypt.c')
-rw-r--r--src/vnet/ipsec/esp_encrypt.c44
1 files changed, 21 insertions, 23 deletions
diff --git a/src/vnet/ipsec/esp_encrypt.c b/src/vnet/ipsec/esp_encrypt.c
index 730a2b83c11..186e122793d 100644
--- a/src/vnet/ipsec/esp_encrypt.c
+++ b/src/vnet/ipsec/esp_encrypt.c
@@ -91,7 +91,9 @@ format_esp_encrypt_trace (u8 * s, va_list * args)
/* pad packet in input buffer */
static_always_inline u8 *
-esp_add_footer_and_icv (vlib_buffer_t * b, u8 block_size, u8 icv_sz)
+esp_add_footer_and_icv (vlib_buffer_t * b, u8 block_size, u8 icv_sz,
+ u16 * next, vlib_node_runtime_t * node,
+ u16 buffer_data_size)
{
static const u8 pad_data[ESP_MAX_BLOCK_SIZE] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
@@ -104,8 +106,15 @@ esp_add_footer_and_icv (vlib_buffer_t * b, u8 block_size, u8 icv_sz)
esp_footer_t *f = (esp_footer_t *) (vlib_buffer_get_current (b) +
new_length - sizeof (esp_footer_t));
+ if (b->current_data + new_length + icv_sz > buffer_data_size)
+ {
+ b->error = node->errors[ESP_ENCRYPT_ERROR_NO_TRAILER_SPACE];
+ next[0] = ESP_ENCRYPT_NEXT_DROP;
+ return 0;
+ }
+
if (pad_bytes)
- clib_memcpy_fast ((u8 *) f - pad_bytes, pad_data, ESP_MAX_BLOCK_SIZE);
+ clib_memcpy_fast ((u8 *) f - pad_bytes, pad_data, pad_bytes);
f->pad_length = pad_bytes;
b->current_length = new_length + icv_sz;
@@ -188,19 +197,6 @@ esp_get_ip6_hdr_len (ip6_header_t * ip6)
return len;
}
-static_always_inline int
-esp_trailer_icv_overflow (vlib_node_runtime_t * node, vlib_buffer_t * b,
- u16 * next, u16 buffer_data_size)
-{
- if (b->current_data + b->current_length <= buffer_data_size)
- return 0;
-
- b->current_length -= buffer_data_size - b->current_data;
- b->error = node->errors[ESP_ENCRYPT_ERROR_NO_TRAILER_SPACE];
- next[0] = ESP_ENCRYPT_NEXT_DROP;
- return 1;
-}
-
static_always_inline void
esp_process_ops (vlib_main_t * vm, vlib_node_runtime_t * node,
vnet_crypto_op_t * ops, vlib_buffer_t * b[], u16 * nexts)
@@ -326,11 +322,12 @@ esp_encrypt_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
if (ipsec_sa_is_set_IS_TUNNEL (sa0))
{
payload = vlib_buffer_get_current (b[0]);
- next_hdr_ptr = esp_add_footer_and_icv (b[0], block_sz, icv_sz);
- payload_len = b[0]->current_length;
-
- if (esp_trailer_icv_overflow (node, b[0], next, buffer_data_size))
+ next_hdr_ptr = esp_add_footer_and_icv (b[0], block_sz, icv_sz,
+ next, node,
+ buffer_data_size);
+ if (!next_hdr_ptr)
goto trace;
+ payload_len = b[0]->current_length;
/* ESP header */
hdr_len += sizeof (*esp);
@@ -389,11 +386,12 @@ esp_encrypt_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
vlib_buffer_advance (b[0], ip_len);
payload = vlib_buffer_get_current (b[0]);
- next_hdr_ptr = esp_add_footer_and_icv (b[0], block_sz, icv_sz);
- payload_len = b[0]->current_length;
-
- if (esp_trailer_icv_overflow (node, b[0], next, buffer_data_size))
+ next_hdr_ptr = esp_add_footer_and_icv (b[0], block_sz, icv_sz,
+ next, node,
+ buffer_data_size);
+ if (!next_hdr_ptr)
goto trace;
+ payload_len = b[0]->current_length;
/* ESP header */
hdr_len += sizeof (*esp);