diff options
author | Matthew Smith <mgsmith@netgate.com> | 2019-07-08 14:45:04 -0500 |
---|---|---|
committer | Neale Ranns <nranns@cisco.com> | 2019-07-12 14:23:28 +0000 |
commit | 401aedfb032d69daa876544e8e0a2973d69c50ac (patch) | |
tree | 4c4caf2f1a84bc0548b5973fc5794bab487e2649 /src/vnet/ipsec/esp_encrypt.c | |
parent | 43ba29267b1f1db04cba0af1f994a5c8477ca870 (diff) |
ipsec: drop outbound ESP when no crypto alg set
Type: fix
If a tunnel interface has the crypto alg set on the outbound SA to
IPSEC_CRYPTO_ALG_NONE and packets are sent out that interface,
the attempt to write an ESP trailer on the packet occurs at the
wrong offset and the vnet buffer opaque data is corrupted, which
can result in a SEGV when a subsequent node attempts to use that
data.
When an outbound SA is set on a tunnel interface which has no crypto
alg set, add a node to the ip{4,6}-output feature arcs which drops all
packets leaving that interface instead of adding the node which would
try to encrypt the packets.
Change-Id: Ie0ac8d8fdc8a035ab8bb83b72b6a94161bebaa48
Signed-off-by: Matthew Smith <mgsmith@netgate.com>
Diffstat (limited to 'src/vnet/ipsec/esp_encrypt.c')
-rw-r--r-- | src/vnet/ipsec/esp_encrypt.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/src/vnet/ipsec/esp_encrypt.c b/src/vnet/ipsec/esp_encrypt.c index c879a404b54..041b268975d 100644 --- a/src/vnet/ipsec/esp_encrypt.c +++ b/src/vnet/ipsec/esp_encrypt.c @@ -666,6 +666,137 @@ VNET_FEATURE_INIT (esp6_encrypt_tun_feat_node, static) = }; /* *INDENT-ON* */ +typedef struct +{ + u32 sa_index; +} esp_no_crypto_trace_t; + +static u8 * +format_esp_no_crypto_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + esp_no_crypto_trace_t *t = va_arg (*args, esp_no_crypto_trace_t *); + + s = format (s, "esp-no-crypto: sa-index %u", t->sa_index); + + return s; +} + +enum +{ + ESP_NO_CRYPTO_NEXT_DROP, + ESP_NO_CRYPTO_N_NEXT, +}; + +enum +{ + ESP_NO_CRYPTO_ERROR_RX_PKTS, +}; + +static char *esp_no_crypto_error_strings[] = { + "Outbound ESP packets received", +}; + +always_inline uword +esp_no_crypto_inline (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs; + u16 nexts[VLIB_FRAME_SIZE], *next = nexts; + u32 *from = vlib_frame_vector_args (frame); + u32 n_left = frame->n_vectors; + + vlib_get_buffers (vm, from, b, n_left); + + while (n_left > 0) + { + u32 next0; + u32 sa_index0; + + /* packets are always going to be dropped, but get the sa_index */ + sa_index0 = *(u32 *) vnet_feature_next_with_data (&next0, b[0], + sizeof (sa_index0)); + + next[0] = ESP_NO_CRYPTO_NEXT_DROP; + + if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED)) + { + esp_no_crypto_trace_t *tr = vlib_add_trace (vm, node, b[0], + sizeof (*tr)); + tr->sa_index = sa_index0; + } + + n_left -= 1; + next += 1; + b += 1; + } + + vlib_node_increment_counter (vm, node->node_index, + ESP_NO_CRYPTO_ERROR_RX_PKTS, frame->n_vectors); + + vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors); + + return frame->n_vectors; +} + +VLIB_NODE_FN (esp4_no_crypto_tun_node) (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + return esp_no_crypto_inline (vm, node, from_frame); +} + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (esp4_no_crypto_tun_node) = +{ + .name = "esp4-no-crypto", + .vector_size = sizeof (u32), + .format_trace = format_esp_no_crypto_trace, + .n_errors = ARRAY_LEN(esp_no_crypto_error_strings), + .error_strings = esp_no_crypto_error_strings, + .n_next_nodes = ESP_NO_CRYPTO_N_NEXT, + .next_nodes = { + [ESP_NO_CRYPTO_NEXT_DROP] = "ip4-drop", + }, +}; + +VNET_FEATURE_INIT (esp4_no_crypto_tun_feat_node, static) = +{ + .arc_name = "ip4-output", + .node_name = "esp4-no-crypto", + .runs_before = VNET_FEATURES ("adj-midchain-tx"), +}; + +VLIB_NODE_FN (esp6_no_crypto_tun_node) (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + return esp_no_crypto_inline (vm, node, from_frame); +} + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (esp6_no_crypto_tun_node) = +{ + .name = "esp6-no-crypto", + .vector_size = sizeof (u32), + .format_trace = format_esp_no_crypto_trace, + .n_errors = ARRAY_LEN(esp_no_crypto_error_strings), + .error_strings = esp_no_crypto_error_strings, + .n_next_nodes = ESP_NO_CRYPTO_N_NEXT, + .next_nodes = { + [ESP_NO_CRYPTO_NEXT_DROP] = "ip6-drop", + }, +}; + +VNET_FEATURE_INIT (esp6_no_crypto_tun_feat_node, static) = +{ + .arc_name = "ip6-output", + .node_name = "esp6-no-crypto", + .runs_before = VNET_FEATURES ("adj-midchain-tx"), +}; +/* *INDENT-ON* */ + /* * fd.io coding-style-patch-verification: ON * |