Fix UDP length check for local IP/UDP lookup and error handling. 64/464/1
authorJohn Lo <loj@cisco.com>
Thu, 3 Mar 2016 05:25:54 +0000 (00:25 -0500)
committerJohn Lo <loj@cisco.com>
Thu, 3 Mar 2016 05:25:54 +0000 (00:25 -0500)
Change-Id: If6695e19e5a1e5471e56099e2cf31794c73f3303
Signed-off-by: John Lo <loj@cisco.com>
vnet/vnet/ip/udp_local.c

index c9355d2..253ad0f 100644 (file)
@@ -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);