summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Lo <loj@cisco.com>2016-03-03 00:25:54 -0500
committerJohn Lo <loj@cisco.com>2016-03-03 00:25:54 -0500
commit76f78ec39af1f3af5a0b1f351aa95761cd2dd6eb (patch)
tree652fb514109f55eb9ef486f78b51b67a5bb10dae
parent2df2e3d7d5226891e974207aa10d1d6e69418cbf (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.c31
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);