ip: fix use-after-free in reassembly 00/22500/2
authorBenoît Ganne <bganne@cisco.com>
Fri, 19 Jul 2019 11:42:12 +0000 (13:42 +0200)
committerAndrew Yourtchenko <ayourtch@gmail.com>
Thu, 3 Oct 2019 16:14:36 +0000 (16:14 +0000)
 - ip{4,6}_reass_finalize() frees the reassembly context: do not access
it after the call.
 - traces access reassembly context: free it after and not before
tracing.

Type: fix

Change-Id: Ia3aaea9c7b74932e249e013be04b9bd7298fd187
Signed-off-by: Benoît Ganne <bganne@cisco.com>
(cherry picked from commit 2d0ebd7ebc555565868038a09d80a61f5de29430)

src/vnet/ip/reass/ip4_full_reass.c
src/vnet/ip/reass/ip6_full_reass.c

index 7cf4f43..73e820f 100644 (file)
@@ -1040,11 +1040,12 @@ ip4_full_reass_update (vlib_main_t * vm, vlib_node_runtime_t * node,
       reass->data_len == reass->last_packet_octet + 1)
     {
       *handoff_thread_idx = reass->sendout_thread_index;
+      int handoff =
+       reass->memory_owner_thread_index != reass->sendout_thread_index;
       rc =
        ip4_full_reass_finalize (vm, node, rm, rt, reass, bi0, next0, error0,
                                 is_custom_app);
-      if (IP4_REASS_RC_OK == rc
-         && reass->memory_owner_thread_index != reass->sendout_thread_index)
+      if (IP4_REASS_RC_OK == rc && handoff)
        {
          rc = IP4_REASS_RC_HANDOFF;
        }
index ef10149..10acd0e 100644 (file)
@@ -885,13 +885,13 @@ ip6_full_reass_update (vlib_main_t * vm, vlib_node_runtime_t * node,
       else
        {
          // overlapping fragment - not allowed by RFC 8200
-         ip6_full_reass_drop_all (vm, node, rm, reass);
-         ip6_full_reass_free (rm, rt, reass);
          if (PREDICT_FALSE (fb->flags & VLIB_BUFFER_IS_TRACED))
            {
              ip6_full_reass_add_trace (vm, node, rm, reass, *bi0,
                                        RANGE_OVERLAP, ~0);
            }
+         ip6_full_reass_drop_all (vm, node, rm, reass);
+         ip6_full_reass_free (rm, rt, reass);
          *next0 = IP6_FULL_REASSEMBLY_NEXT_DROP;
          *error0 = IP6_ERROR_REASS_OVERLAPPING_FRAGMENT;
          return IP6_FULL_REASS_RC_OK;
@@ -911,11 +911,12 @@ check_if_done_maybe:
       reass->data_len == reass->last_packet_octet + 1)
     {
       *handoff_thread_idx = reass->sendout_thread_index;
+      int handoff =
+       reass->memory_owner_thread_index != reass->sendout_thread_index;
       ip6_full_reass_rc_t rc =
        ip6_full_reass_finalize (vm, node, rm, rt, reass, bi0, next0, error0,
                                 is_custom_app);
-      if (IP6_FULL_REASS_RC_OK == rc
-         && reass->memory_owner_thread_index != reass->sendout_thread_index)
+      if (IP6_FULL_REASS_RC_OK == rc && handoff)
        {
          return IP6_FULL_REASS_RC_HANDOFF;
        }