aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjohny <jan.cavojsky@pantheon.tech>2019-10-11 18:28:51 +0200
committerOle Trøan <otroan@employees.org>2019-12-05 15:13:48 +0000
commit17478e4eb81d384f171ca27c9110a051cd434f16 (patch)
tree0709ffd67003d5fcd2859fa233ef297198fdf951
parent70d8ef89a5d9e38d4f35517c0f64009c47b76c4d (diff)
ip: fix cancel termination after receive malformed ip6 packet
This fix is for cancel termination of vpp after receive malformed packet type of ip6.To avoid termination of vpp are checked if are missing data in packet. This occours, when payload length in ip6 header packet is more than real count of data in packet. When this error occours, packet is ignore. Type: fix Ticket: VPP-1693, VPP-1694 Change-Id: I9d9ecea7b75c8702cb31aa8051c8d4d7ce19659d Signed-off-by: johny <jan.cavojsky@pantheon.tech>
-rw-r--r--src/vnet/ip/ip.h2
-rw-r--r--src/vnet/ip/ip6_forward.c71
2 files changed, 68 insertions, 5 deletions
diff --git a/src/vnet/ip/ip.h b/src/vnet/ip/ip.h
index 22daaabc096..587ec85c229 100644
--- a/src/vnet/ip/ip.h
+++ b/src/vnet/ip/ip.h
@@ -213,7 +213,6 @@ ip_calculate_l4_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
n_this_buffer = n_ip_bytes_this_buffer - ip_header_size;
if (PREDICT_FALSE (n_this_buffer >> 31))
{ /* error - ip header don't fit this buffer */
- ASSERT (0);
return 0xfefe;
}
}
@@ -235,7 +234,6 @@ ip_calculate_l4_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
if (!(p0->flags & VLIB_BUFFER_NEXT_PRESENT))
{
- ASSERT (0); /* error - more buffer expected */
return 0xfefe;
}
diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c
index ae7083ba27b..959ff890f73 100644
--- a/src/vnet/ip/ip6_forward.c
+++ b/src/vnet/ip/ip6_forward.c
@@ -1136,6 +1136,52 @@ VNET_FEATURE_ARC_INIT (ip6_local) =
};
/* *INDENT-ON* */
+static_always_inline u8
+ip6_tcp_udp_icmp_bad_length (vlib_main_t * vm, vlib_buffer_t * p0)
+{
+
+ u16 payload_length_host_byte_order;
+ u32 n_this_buffer, n_bytes_left;
+ ip6_header_t *ip0 = vlib_buffer_get_current (p0);
+ u32 headers_size = sizeof (ip0[0]);
+ u8 *data_this_buffer;
+
+
+ data_this_buffer = (u8 *) (ip0 + 1);
+
+ ip6_hop_by_hop_ext_t *ext_hdr = (ip6_hop_by_hop_ext_t *) data_this_buffer;
+
+ /* validate really icmp6 next */
+
+ if (!(ext_hdr->next_hdr == IP_PROTOCOL_ICMP6)
+ || (ext_hdr->next_hdr == IP_PROTOCOL_UDP))
+ return 0;
+
+
+ payload_length_host_byte_order = clib_net_to_host_u16 (ip0->payload_length);
+ n_bytes_left = n_this_buffer = payload_length_host_byte_order;
+
+ if (p0)
+ {
+ u32 n_ip_bytes_this_buffer =
+ p0->current_length - (((u8 *) ip0 - p0->data) - p0->current_data);
+ if (n_this_buffer + headers_size > n_ip_bytes_this_buffer)
+ {
+ n_this_buffer = p0->current_length > headers_size ?
+ n_ip_bytes_this_buffer - headers_size : 0;
+ }
+ }
+
+ n_bytes_left -= n_this_buffer;
+ n_bytes_left -= p0->total_length_not_including_first_buffer;
+
+ if (n_bytes_left == 0)
+ return 0;
+ else
+ return 1;
+}
+
+
always_inline uword
ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
vlib_frame_t * frame, int head_of_feature_arc)
@@ -1250,16 +1296,28 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
{
flags[0] = ip6_tcp_udp_icmp_validate_checksum (vm, b[0]);
good_l4_csum[0] = flags[0] & VNET_BUFFER_F_L4_CHECKSUM_CORRECT;
+ error[0] = IP6_ERROR_UNKNOWN_PROTOCOL;
+ }
+ else
+ {
+ if (ip6_tcp_udp_icmp_bad_length (vm, b[0]))
+ error[0] = IP6_ERROR_BAD_LENGTH;
}
if (PREDICT_FALSE (need_csum[1]))
{
flags[1] = ip6_tcp_udp_icmp_validate_checksum (vm, b[1]);
good_l4_csum[1] = flags[1] & VNET_BUFFER_F_L4_CHECKSUM_CORRECT;
+ error[1] = IP6_ERROR_UNKNOWN_PROTOCOL;
+ }
+ else
+ {
+ if (ip6_tcp_udp_icmp_bad_length (vm, b[1]))
+ error[1] = IP6_ERROR_BAD_LENGTH;
}
- error[0] = IP6_ERROR_UNKNOWN_PROTOCOL;
+
error[0] = len_diff[0] < 0 ? IP6_ERROR_UDP_LENGTH : error[0];
- error[1] = IP6_ERROR_UNKNOWN_PROTOCOL;
+
error[1] = len_diff[1] < 0 ? IP6_ERROR_UDP_LENGTH : error[1];
STATIC_ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_UDP ==
@@ -1391,9 +1449,16 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
{
flags = ip6_tcp_udp_icmp_validate_checksum (vm, b[0]);
good_l4_csum = flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT;
+ error = IP6_ERROR_UNKNOWN_PROTOCOL;
}
+ else
+ {
+ if (ip6_tcp_udp_icmp_bad_length (vm, b[0]))
+ error = IP6_ERROR_BAD_LENGTH;
+ }
+
+
- error = IP6_ERROR_UNKNOWN_PROTOCOL;
error = len_diff < 0 ? IP6_ERROR_UDP_LENGTH : error;
STATIC_ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_UDP ==