Blob Blame History Raw
From 3bef22791deec6280244b43b028044ad7015c5d1 Mon Sep 17 00:00:00 2001
From: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Date: Fri, 24 Dec 2021 18:57:54 +0300
Subject: [PATCH 09/10] fixup: attempt to disable rseq at the thread start

Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
---
 criu/clone-noasan.c | 49 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/criu/clone-noasan.c b/criu/clone-noasan.c
index d657ea2e8..bcda7865b 100644
--- a/criu/clone-noasan.c
+++ b/criu/clone-noasan.c
@@ -2,6 +2,10 @@
 #include <sched.h>
 #include <unistd.h>
 
+#if defined(__x86_64__) && (__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 34)
+#include <sys/rseq.h>
+#endif
+
 #include <compel/plugins/std/syscall-codes.h>
 
 #include "sched.h"
@@ -34,16 +38,55 @@
  *	... wait for process to finish ...
  *	unlock_last_pid
  */
+
+#if defined(__x86_64__) && defined(RSEQ_SIG)
+static inline void *
+thread_pointer (void)
+{
+  void *result;
+  asm ("mov %%fs:0, %0" : "=r" (result));
+  return result;
+}
+
+static inline void
+unregister_rseq_asdf (void)
+{
+	/* unregister rseq */
+	syscall(__NR_rseq, (void *)((char *) thread_pointer () + __rseq_offset), __rseq_size, 1, RSEQ_SIG);
+}
+#else
+static inline void
+unregister_rseq_asdf (void)
+{
+}
+#endif
+
+struct call_fn_args {
+	int (*fn)(void *);
+	void *arg;
+};
+
+int call_fn(void *arg)
+{
+	struct call_fn_args *a = arg;
+	unregister_rseq_asdf();
+	return a->fn(a->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 +121,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_rseq_asdf();
 		exit(fn(arg));
+	}
 	return pid;
 }
-- 
2.34.1