From d43ad9913c19afa6d80cb8124015d47361152db8 Mon Sep 17 00:00:00 2001 From: bb-cat Date: Wed, 2 Mar 2022 15:00:43 +0800 Subject: [PATCH 10/16] clone-noasan: unregister rseq at the thread start for new glibc Fresh glibc does rseq registration by default during start_thread(). [ see https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=95e114a0919d844d8fe07839cb6538b7f5ee920e ] This cause process crashes during memory restore procedure, because memory which corresponds to the struct rseq will be overwritten. See also ("nptl: Add public rseq symbols and ") https://sourceware.org/git?p=glibc.git;a=commit;h=c901c3e764d7c7079f006b4e21e877d5036eb4f5 ("nptl: Add for defining __thread_pointer") https://sourceware.org/git?p=glibc.git;a=commit;h=8dbeb0561eeb876f557ac9eef5721912ec074ea5 Signed-off-by: Alexander Mikhalitsyn --- criu/clone-noasan.c | 42 +++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/criu/clone-noasan.c b/criu/clone-noasan.c index d657ea2..5f8dd1b 100644 --- a/criu/clone-noasan.c +++ b/criu/clone-noasan.c @@ -2,6 +2,13 @@ #include #include +#ifdef __has_include +#if __has_include ("sys/rseq.h") +#include +#include "asm/thread_pointer.h" +#endif +#endif + #include #include "sched.h" @@ -34,16 +41,45 @@ * ... wait for process to finish ... * unlock_last_pid */ + +#if defined(RSEQ_SIG) +static inline void unregister_glibc_rseq(void) +{ + /* unregister rseq */ + syscall(__NR_rseq, (void *)((char *)__criu_thread_pointer() + __rseq_offset), __rseq_size, 1, RSEQ_SIG); +} +#else +static inline void unregister_glibc_rseq(void) +{ +} +#endif + +struct call_fn_args { + int (*fn)(void *); + void *arg; +}; + +int call_fn(void *arg) +{ + struct call_fn_args *cargs = arg; + unregister_glibc_rseq(); + return cargs->fn(cargs->arg); +} + int clone_noasan(int (*fn)(void *), int flags, void *arg) { void *stack_ptr = (void *)round_down((unsigned long)&stack_ptr - 1024, 16); + struct call_fn_args a = { + .fn = fn, + .arg = arg, + }; BUG_ON((flags & CLONE_VM) && !(flags & CLONE_VFORK)); /* * Reserve some bytes for clone() internal needs * and use as stack the address above this area. */ - return clone(fn, stack_ptr, flags, arg); + return clone(call_fn, stack_ptr, flags, (void *)&a); } int clone3_with_pid_noasan(int (*fn)(void *), void *arg, int flags, int exit_signal, pid_t pid) @@ -78,7 +114,9 @@ int clone3_with_pid_noasan(int (*fn)(void *), void *arg, int flags, int exit_sig c_args.set_tid = ptr_to_u64(&pid); c_args.set_tid_size = 1; pid = syscall(__NR_clone3, &c_args, sizeof(c_args)); - if (pid == 0) + if (pid == 0) { + unregister_glibc_rseq(); exit(fn(arg)); + } return pid; } -- 2.30.0