criu/0010-clone-noasan-unregister-rseq-at-the-thread-start-for.patch

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