[CRIU] [PATCH 5/6] restorer: Workaround ASan false-positives after clone().
Andrey Ryabinin
aryabinin at virtuozzo.com
Mon Feb 6 02:14:16 PST 2017
ASan doesn't play nicely with clone if we use current stack for
child task. ASan puts local variables on the fake stack
to catch use-after-return bug:
https://github.com/google/sanitizers/wiki/AddressSanitizerUseAfterReturn#algorithm
So it's become easy to overflow this fake stack frame in cloned child.
We need a real stack for clone().
To workaround this we add clone_noasan() not-instrumented wrapper for
clone(). Unfortunately we can't use __attrbute__((no_sanitize_addresss))
for this because of bug in GCC > 6:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69863
So the only way is to put this wrapper in separate non-instrumented file.
Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
---
criu/Makefile.crtools | 2 ++
criu/clone-noasan.c | 33 +++++++++++++++++++++++++++++++++
criu/cr-restore.c | 12 +++---------
criu/include/clone-noasan.h | 6 ++++++
4 files changed, 44 insertions(+), 9 deletions(-)
create mode 100644 criu/clone-noasan.c
create mode 100644 criu/include/clone-noasan.h
diff --git a/criu/Makefile.crtools b/criu/Makefile.crtools
index 8188129..e095d01 100644
--- a/criu/Makefile.crtools
+++ b/criu/Makefile.crtools
@@ -1,5 +1,6 @@
ccflags-y += -iquote criu/$(ARCH)
ccflags-y += $(COMPEL_UAPI_INCLUDES)
+CFLAGS_REMOVE_clone-noasan.o += $(CFLAGS-ASAN)
obj-y += action-scripts.o
obj-y += external.o
@@ -8,6 +9,7 @@ obj-y += bfd.o
obj-y += bitmap.o
obj-y += cgroup.o
obj-y += cgroup-props.o
+obj-y += clone-noasan.o
obj-y += cr-check.o
obj-y += cr-dedup.o
obj-y += cr-dump.o
diff --git a/criu/clone-noasan.c b/criu/clone-noasan.c
new file mode 100644
index 0000000..c5171b1
--- /dev/null
+++ b/criu/clone-noasan.c
@@ -0,0 +1,33 @@
+#include <sched.h>
+#include "common/compiler.h"
+
+/*
+ * ASan doesn't play nicely with clone if we use current stack for
+ * child task. ASan puts local variables on the fake stack
+ * to catch use-after-return bug:
+ * https://github.com/google/sanitizers/wiki/AddressSanitizerUseAfterReturn#algorithm
+ *
+ * So it's become easy to overflow this fake stack frame in cloned child.
+ * We need a real stack for clone().
+ *
+ * To workaround this we add clone_noasan() not-instrumented wrapper for
+ * clone(). Unfortunately we can't use __attrbute__((no_sanitize_addresss))
+ * for this because of bug in GCC > 6:
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69863
+ *
+ * So the only way is to put this wrapper in separate non-instrumented file
+ */
+int clone_noasan(int (*fn)(void *), int flags, void *arg)
+{
+ /*
+ * Reserve some space for clone() to locate arguments
+ * and retcode in this place
+ */
+ char stack[128] __stack_aligned__;
+ char *stack_ptr = &stack[sizeof(stack)];
+ int ret;
+
+ ret = clone(fn, stack_ptr, flags, arg);
+ return ret;
+}
+
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index ee6b848..a5743fb 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -27,6 +27,7 @@
#include <compel/ptrace.h>
#include "common/compiler.h"
+#include "clone-noasan.h"
#include "cr_options.h"
#include "servicefd.h"
#include "image.h"
@@ -914,12 +915,6 @@ static int restore_one_task(int pid, CoreEntry *core)
/* All arguments should be above stack, because it grows down */
struct cr_clone_arg {
- /*
- * Reserve some space for clone() to locate arguments
- * and retcode in this place
- */
- char stack[128] __stack_aligned__;
- char stack_ptr[0];
struct pstree_item *item;
unsigned long clone_flags;
int fd;
@@ -1042,9 +1037,8 @@ static inline int fork_with_pid(struct pstree_item *item)
* The cgroup namespace is also unshared explicitly in the
* move_in_cgroup(), so drop this flag here as well.
*/
- ret = clone(restore_task_with_children, ca.stack_ptr,
- (ca.clone_flags & ~(CLONE_NEWNET | CLONE_NEWCGROUP)) | SIGCHLD, &ca);
-
+ ret = clone_noasan(restore_task_with_children,
+ (ca.clone_flags & ~(CLONE_NEWNET | CLONE_NEWCGROUP)) | SIGCHLD, &ca);
if (ret < 0) {
pr_perror("Can't fork for %d", pid);
goto err_unlock;
diff --git a/criu/include/clone-noasan.h b/criu/include/clone-noasan.h
new file mode 100644
index 0000000..8ef75fa
--- /dev/null
+++ b/criu/include/clone-noasan.h
@@ -0,0 +1,6 @@
+#ifndef __CR_CLONE_NOASAN_H__
+#define __CR_CLONE_NOASAN_H__
+
+int clone_noasan(int (*fn)(void *), int flags, void *arg);
+
+#endif /* __CR_CLONE_NOASAN_H__ */
--
2.10.2
More information about the CRIU
mailing list