Hello,

I am trying to use Address Sanitizer to detect issues.
With a simple code of use-after-free it works, but with postponed free,
there
is no detection of the problem.

Compilation is done with:
make -j CFLAGS="-O0 -g3 -Werror -fsanitize=address
-fno-omit-frame-pointer -fno-common"

Simple code:

--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -2742,6 +2742,12 @@ dp_netdev_flow_offload_main(void *data OVS_UNUSED)
                                  &dp_flow_offload.mutex);
              ovsrcu_quiesce_end();
          }
+        if (1) {
+            char *xx = xmalloc(80);
+            xx[0] = 'a';
+            free(xx);
+            xx[1] = 'b';
+        }
          list = ovs_list_pop_front(&dp_flow_offload.list);

Running a test:
make -j check TESTSUITEFLAGS=991

Problem is detected:
991: dpif-netdev - partial hw offload - dummy        FAILED
(ovs-macros.at:242)

tests/testsuite.dir/0991/asan.30479
=================================================================
==30479== ERROR: AddressSanitizer: heap-use-after-free on address
0x600e0001bfb1 at pc 0x20dcb79 bp 0x7fb60ca1e200 sp 0x7fb60ca1e1f0
WRITE of size 1 at 0x600e0001bfb1 thread T17
...

With RCU, if we force the free:
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 300861ca5..71b48dbd8 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -2726,6 +2726,14 @@ err_free:
      return -1;
  }

+static volatile bool postpone_executed = false;
+static void
+flagged_free(void *p)
+{
+    free(p);
+    postpone_executed = true;
+}
+
  static void *
  dp_netdev_flow_offload_main(void *data OVS_UNUSED)
  {
@@ -2742,6 +2750,14 @@ dp_netdev_flow_offload_main(void *data OVS_UNUSED)
                                  &dp_flow_offload.mutex);
              ovsrcu_quiesce_end();
          }
+        if (1) {
+            char *xx = xmalloc(80);
+            xx[0] = 'a';
+            ovsrcu_postpone(flagged_free, xx);
+            ovsrcu_quiesce();
+            while (!postpone_executed);
+            xx[1] = 'b';
+        }
          list = ovs_list_pop_front(&dp_flow_offload.list);

The problem is also detected.

However, if removing the flag:
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -2726,12 +2726,10 @@ err_free:
      return -1;
  }

-static volatile bool postpone_executed = false;
  static void
  flagged_free(void *p)
  {
      free(p);
-    postpone_executed = true;
  }

  static void *
@@ -2755,7 +2753,6 @@ dp_netdev_flow_offload_main(void *data OVS_UNUSED)
              xx[0] = 'a';
              ovsrcu_postpone(flagged_free, xx);
              ovsrcu_quiesce();
-            while (!postpone_executed);
              xx[1] = 'b';
          }
          list = ovs_list_pop_front(&dp_flow_offload.list);

The problem is not detected.

This way it is up to a race between the RCU thread and the write of xx[1].
Any thoughts of a better tool or technique that is more suitable?

Thanks,
Eli

_______________________________________________
discuss mailing list
disc...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-discuss

Reply via email to