diff options
author | John Lo <loj@cisco.com> | 2016-03-03 00:25:54 -0500 |
---|---|---|
committer | John Lo <loj@cisco.com> | 2016-03-03 00:25:54 -0500 |
commit | 76f78ec39af1f3af5a0b1f351aa95761cd2dd6eb (patch) | |
tree | 652fb514109f55eb9ef486f78b51b67a5bb10dae | |
parent | 2df2e3d7d5226891e974207aa10d1d6e69418cbf (diff) |
Fix UDP length check for local IP/UDP lookup and error handling.
Change-Id: If6695e19e5a1e5471e56099e2cf31794c73f3303
Signed-off-by: John Lo <loj@cisco.com>
-rw-r--r-- | vnet/vnet/ip/udp_local.c | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/vnet/vnet/ip/udp_local.c b/vnet/vnet/ip/udp_local.c index c9355d2a322..253ad0f369e 100644 --- a/vnet/vnet/ip/udp_local.c +++ b/vnet/vnet/ip/udp_local.c @@ -133,7 +133,7 @@ udp46_input_inline (vlib_main_t * vm, advance1 = sizeof(ip6_header_t); } - if (PREDICT_FALSE(b0->current_length < advance0 + sizeof (h0))) + if (PREDICT_FALSE(b0->current_length < advance0 + sizeof (*h0))) { error0 = UDP_ERROR_LENGTH_ERROR; next0 = UDP_INPUT_NEXT_DROP; @@ -143,9 +143,15 @@ udp46_input_inline (vlib_main_t * vm, vlib_buffer_advance (b0, advance0); h0 = vlib_buffer_get_current (b0); error0 = next0 = 0; + if (PREDICT_FALSE(clib_net_to_host_u16(h0->length) > + vlib_buffer_length_in_chain(vm, b0))) + { + error0 = UDP_ERROR_LENGTH_ERROR; + next0 = UDP_INPUT_NEXT_DROP; + } } - if (PREDICT_FALSE(b1->current_length < advance1 + sizeof (h1))) + if (PREDICT_FALSE(b1->current_length < advance1 + sizeof (*h1))) { error1 = UDP_ERROR_LENGTH_ERROR; next1 = UDP_INPUT_NEXT_DROP; @@ -155,9 +161,14 @@ udp46_input_inline (vlib_main_t * vm, vlib_buffer_advance (b1, advance1); h1 = vlib_buffer_get_current (b1); error1 = next1 = 0; + if (PREDICT_FALSE(clib_net_to_host_u16(h1->length) > + vlib_buffer_length_in_chain(vm, b1))) + { + error1 = UDP_ERROR_LENGTH_ERROR; + next1 = UDP_INPUT_NEXT_DROP; + } } - /* Index sparse array with network byte order. */ dst_port0 = (error0 == 0) ? h0->dst_port : 0; dst_port1 = (error1 == 0) ? h1->dst_port : 0; @@ -166,10 +177,10 @@ udp46_input_inline (vlib_main_t * vm, next0 = (error0 == 0) ? vec_elt(rt->next_by_dst_port, i0) : next0; next1 = (error1 == 0) ? vec_elt(rt->next_by_dst_port, i1) : next1; - if (PREDICT_TRUE (error0 == 0)) - b0->error = node->errors[next0 == SPARSE_VEC_INVALID_INDEX ? UDP_ERROR_NO_LISTENER : UDP_ERROR_NONE]; - if (PREDICT_TRUE (error1 == 0)) - b1->error = node->errors[next1 == SPARSE_VEC_INVALID_INDEX ? UDP_ERROR_NO_LISTENER : UDP_ERROR_NONE]; + b0->error = node->errors[next0 == SPARSE_VEC_INVALID_INDEX ? + UDP_ERROR_NO_LISTENER : error0]; + b1->error = node->errors[next1 == SPARSE_VEC_INVALID_INDEX ? + UDP_ERROR_NO_LISTENER : error1]; if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { @@ -223,7 +234,7 @@ udp46_input_inline (vlib_main_t * vm, else advance0 = sizeof(ip6_header_t); - if (PREDICT_FALSE(b0->current_length < advance0 + sizeof (h0))) + if (PREDICT_FALSE(b0->current_length < advance0 + sizeof (*h0))) { b0->error = node->errors[UDP_ERROR_LENGTH_ERROR]; next0 = UDP_INPUT_NEXT_DROP; @@ -234,8 +245,8 @@ udp46_input_inline (vlib_main_t * vm, h0 = vlib_buffer_get_current (b0); - if (PREDICT_TRUE - (clib_net_to_host_u16(h0->length) <= b0->current_length)) + if (PREDICT_TRUE(clib_net_to_host_u16(h0->length) <= + vlib_buffer_length_in_chain(vm, b0))) { i0 = sparse_vec_index (rt->next_by_dst_port, h0->dst_port); next0 = vec_elt(rt->next_by_dst_port, i0); |