[ovs-discuss] ASAN RCU use-after-free
Eli Britstein
elibr at nvidia.com
Tue Jan 5 15:05:37 UTC 2021
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
More information about the discuss
mailing list