see https://github.com/checkpoint-restore/criu/issues/1696 and https://github.com/checkpoint-restore/criu/pull/1706
103 lines
2.8 KiB
Diff
103 lines
2.8 KiB
Diff
From d43ad9913c19afa6d80cb8124015d47361152db8 Mon Sep 17 00:00:00 2001
|
|
From: bb-cat <ningyu9@huawei.com>
|
|
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 <sys/rseq.h>")
|
|
https://sourceware.org/git?p=glibc.git;a=commit;h=c901c3e764d7c7079f006b4e21e877d5036eb4f5
|
|
("nptl: Add <thread_pointer.h> for defining __thread_pointer")
|
|
https://sourceware.org/git?p=glibc.git;a=commit;h=8dbeb0561eeb876f557ac9eef5721912ec074ea5
|
|
|
|
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
|
|
---
|
|
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 <sched.h>
|
|
#include <unistd.h>
|
|
|
|
+#ifdef __has_include
|
|
+#if __has_include ("sys/rseq.h")
|
|
+#include <sys/rseq.h>
|
|
+#include "asm/thread_pointer.h"
|
|
+#endif
|
|
+#endif
|
|
+
|
|
#include <compel/plugins/std/syscall-codes.h>
|
|
|
|
#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
|
|
|