tcp: validate connections in output 44/21644/5
authorFlorin Coras <fcoras@cisco.com>
Fri, 30 Aug 2019 17:00:30 +0000 (10:00 -0700)
committerJohn Lo <loj@cisco.com>
Tue, 10 Sep 2019 14:11:01 +0000 (14:11 +0000)
Type: feature

This shouldn't happen unless connections are removed after buffers were
enqueued to tcp-output and before tcp-output runs. For instance, packet
is enqueued to tcp output and cleanup is called for connection.

Change-Id: Ib7dd82ffa6cfb21ff5068aba010e0a3497eeea13
Signed-off-by: Florin Coras <fcoras@cisco.com>
src/vnet/tcp/tcp_output.c

index 20031b2..ff281b5 100644 (file)
@@ -2141,6 +2141,10 @@ tcp_output_handle_packet (tcp_connection_t * tc0, vlib_buffer_t * b0,
       *next0 = tc0->next_node_index;
       vnet_buffer (b0)->tcp.next_node_opaque = tc0->next_node_opaque;
     }
+  else
+    {
+      *next0 = TCP_OUTPUT_NEXT_IP_LOOKUP;
+    }
 
   vnet_buffer (b0)->sw_if_index[VLIB_TX] = tc0->c_fib_index;
   vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
@@ -2199,18 +2203,44 @@ tcp46_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
        CLIB_PREFETCH (b[3]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE);
       }
 
-      next[0] = next[1] = TCP_OUTPUT_NEXT_IP_LOOKUP;
-
       tc0 = tcp_connection_get (vnet_buffer (b[0])->tcp.connection_index,
                                thread_index);
       tc1 = tcp_connection_get (vnet_buffer (b[1])->tcp.connection_index,
                                thread_index);
 
-      tcp_output_push_ip (vm, b[0], tc0, is_ip4);
-      tcp_output_push_ip (vm, b[1], tc1, is_ip4);
+      if (PREDICT_TRUE (!tc0 + !tc1 == 0))
+       {
+         tcp_output_push_ip (vm, b[0], tc0, is_ip4);
+         tcp_output_push_ip (vm, b[1], tc1, is_ip4);
 
-      tcp_output_handle_packet (tc0, b[0], error_node, &next[0], is_ip4);
-      tcp_output_handle_packet (tc1, b[1], error_node, &next[1], is_ip4);
+         tcp_output_handle_packet (tc0, b[0], error_node, &next[0], is_ip4);
+         tcp_output_handle_packet (tc1, b[1], error_node, &next[1], is_ip4);
+       }
+      else
+       {
+         if (tc0 != 0)
+           {
+             tcp_output_push_ip (vm, b[0], tc0, is_ip4);
+             tcp_output_handle_packet (tc0, b[0], error_node, &next[0],
+                                       is_ip4);
+           }
+         else
+           {
+             b[0]->error = error_node->errors[TCP_ERROR_INVALID_CONNECTION];
+             next[0] = TCP_OUTPUT_NEXT_DROP;
+           }
+         if (tc1 != 0)
+           {
+             tcp_output_push_ip (vm, b[1], tc1, is_ip4);
+             tcp_output_handle_packet (tc1, b[1], error_node, &next[1],
+                                       is_ip4);
+           }
+         else
+           {
+             b[1]->error = error_node->errors[TCP_ERROR_INVALID_CONNECTION];
+             next[1] = TCP_OUTPUT_NEXT_DROP;
+           }
+       }
 
       b += 2;
       next += 2;
@@ -2226,12 +2256,19 @@ tcp46_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
          CLIB_PREFETCH (b[1]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE);
        }
 
-      next[0] = TCP_OUTPUT_NEXT_IP_LOOKUP;
       tc0 = tcp_connection_get (vnet_buffer (b[0])->tcp.connection_index,
                                thread_index);
 
-      tcp_output_push_ip (vm, b[0], tc0, is_ip4);
-      tcp_output_handle_packet (tc0, b[0], error_node, &next[0], is_ip4);
+      if (PREDICT_TRUE (tc0 != 0))
+       {
+         tcp_output_push_ip (vm, b[0], tc0, is_ip4);
+         tcp_output_handle_packet (tc0, b[0], error_node, &next[0], is_ip4);
+       }
+      else
+       {
+         b[0]->error = error_node->errors[TCP_ERROR_INVALID_CONNECTION];
+         next[0] = TCP_OUTPUT_NEXT_DROP;
+       }
 
       b += 1;
       next += 1;