Commit 148929d6 authored by Andrey Ryabinin's avatar Andrey Ryabinin Committed by Andrei Vagin

restorer: Workaround ASan false-positives after clone().

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.

travis-ci: success for series starting with [1/6] compel/infect: fix out-of-bounds parasite memcpy()
Signed-off-by: 's avatarAndrey Ryabinin <aryabinin@virtuozzo.com>
Reviewed-by: 's avatarDmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 706c0552
ccflags-y += -iquote criu/$(ARCH) ccflags-y += -iquote criu/$(ARCH)
ccflags-y += $(COMPEL_UAPI_INCLUDES) ccflags-y += $(COMPEL_UAPI_INCLUDES)
CFLAGS_REMOVE_clone-noasan.o += $(CFLAGS-ASAN)
obj-y += action-scripts.o obj-y += action-scripts.o
obj-y += external.o obj-y += external.o
...@@ -8,6 +9,7 @@ obj-y += bfd.o ...@@ -8,6 +9,7 @@ obj-y += bfd.o
obj-y += bitmap.o obj-y += bitmap.o
obj-y += cgroup.o obj-y += cgroup.o
obj-y += cgroup-props.o obj-y += cgroup-props.o
obj-y += clone-noasan.o
obj-y += cr-check.o obj-y += cr-check.o
obj-y += cr-dedup.o obj-y += cr-dedup.o
obj-y += cr-dump.o obj-y += cr-dump.o
......
#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;
}
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <compel/ptrace.h> #include <compel/ptrace.h>
#include "common/compiler.h" #include "common/compiler.h"
#include "clone-noasan.h"
#include "cr_options.h" #include "cr_options.h"
#include "servicefd.h" #include "servicefd.h"
#include "image.h" #include "image.h"
...@@ -909,12 +910,6 @@ static int restore_one_task(int pid, CoreEntry *core) ...@@ -909,12 +910,6 @@ static int restore_one_task(int pid, CoreEntry *core)
/* All arguments should be above stack, because it grows down */ /* All arguments should be above stack, because it grows down */
struct cr_clone_arg { 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; struct pstree_item *item;
unsigned long clone_flags; unsigned long clone_flags;
int fd; int fd;
...@@ -1037,9 +1032,8 @@ static inline int fork_with_pid(struct pstree_item *item) ...@@ -1037,9 +1032,8 @@ static inline int fork_with_pid(struct pstree_item *item)
* The cgroup namespace is also unshared explicitly in the * The cgroup namespace is also unshared explicitly in the
* move_in_cgroup(), so drop this flag here as well. * move_in_cgroup(), so drop this flag here as well.
*/ */
ret = clone(restore_task_with_children, ca.stack_ptr, ret = clone_noasan(restore_task_with_children,
(ca.clone_flags & ~(CLONE_NEWNET | CLONE_NEWCGROUP)) | SIGCHLD, &ca); (ca.clone_flags & ~(CLONE_NEWNET | CLONE_NEWCGROUP)) | SIGCHLD, &ca);
if (ret < 0) { if (ret < 0) {
pr_perror("Can't fork for %d", pid); pr_perror("Can't fork for %d", pid);
goto err_unlock; goto err_unlock;
......
#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__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment