[CRIU] [PATCHv3 21/23] x86/parasite: call get_thread_area on 32-bit addr

Dmitry Safonov dsafonov at virtuozzo.com
Fri Dec 9 10:19:47 PST 2016


It's 32-bit syscall and the high-part of address is dropped,
so call it only on 32-bit addr.

Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
 criu/arch/x86/include/asm/compat.h   | 41 ++++++++++++++++++++++++++++++++++++
 criu/arch/x86/include/asm/parasite.h | 23 ++++++++++++++++++--
 criu/arch/x86/include/asm/restorer.h | 13 +++---------
 criu/arch/x86/sigaction_compat.c     | 20 +-----------------
 4 files changed, 66 insertions(+), 31 deletions(-)
 create mode 100644 criu/arch/x86/include/asm/compat.h

diff --git a/criu/arch/x86/include/asm/compat.h b/criu/arch/x86/include/asm/compat.h
new file mode 100644
index 000000000000..8379af452e47
--- /dev/null
+++ b/criu/arch/x86/include/asm/compat.h
@@ -0,0 +1,41 @@
+#ifndef __CR_ASM_COMPAT_H__
+#define __CR_ASM_COMPAT_H__
+
+#ifdef CR_NOGLIBC
+# include <compel/plugins/std/syscall.h>
+# include <compel/plugins/std/syscall-codes.h>
+#else
+# define sys_mmap mmap
+# define sys_munmap munmap
+#endif
+
+#include <sys/mman.h>
+
+static inline void *alloc_compat_syscall_stack(void)
+{
+	void *mem = (void*)sys_mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
+			MAP_32BIT | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+
+	if (mem == MAP_FAILED)
+		return 0;
+	return mem;
+}
+
+static inline void free_compat_syscall_stack(void *mem)
+{
+	long int ret = sys_munmap(mem, PAGE_SIZE);
+
+	if (ret)
+		pr_err("munmap of compat addr %p failed with %ld", mem, ret);
+}
+
+#ifdef CONFIG_COMPAT
+extern unsigned long call32_from_64(void *stack, void *func);
+#endif
+
+#ifndef CR_NOGLIBC
+# undef sys_mmap
+# undef sys_munmap
+#endif
+
+#endif
diff --git a/criu/arch/x86/include/asm/parasite.h b/criu/arch/x86/include/asm/parasite.h
index 302b412afa9c..2385ec16d061 100644
--- a/criu/arch/x86/include/asm/parasite.h
+++ b/criu/arch/x86/include/asm/parasite.h
@@ -3,12 +3,13 @@
 
 #include "asm-generic/string.h"
 #include <compel/plugins/std/syscall-codes.h>
+#include "asm/compat.h"
 
 #ifdef CONFIG_X86_32
 # define __parasite_entry __attribute__((regparm(3)))
 #endif
 
-static void arch_get_user_desc(user_desc_t *desc)
+static int arch_get_user_desc(user_desc_t *desc)
 {
 	int ret = __NR32_get_thread_area;
 	/*
@@ -46,21 +47,39 @@ static void arch_get_user_desc(user_desc_t *desc)
 	if (ret)
 		pr_err("Failed to dump TLS descriptor #%d: %d\n",
 				desc->entry_number, ret);
+	return ret;
 }
 
 static void arch_get_tls(tls_t *ptls)
 {
+	void *syscall_mem;
 	int i;
 
+	syscall_mem = alloc_compat_syscall_stack();
+	if (!syscall_mem) {
+		pr_err("Failed to allocate memory <4Gb for compat syscall\n");
+
+		for (i = 0; i < GDT_ENTRY_TLS_NUM; i++) {
+			user_desc_t *d = &ptls->desc[i];
+
+			d->seg_not_present = 1;
+			d->entry_number = GDT_ENTRY_TLS_MIN + i;
+		}
+		return;
+	}
+
 	for (i = 0; i < GDT_ENTRY_TLS_NUM; i++)
 	{
-		user_desc_t *d = &ptls->desc[i];
+		user_desc_t *d = syscall_mem;
 
 		builtin_memset(d, 0, sizeof(user_desc_t));
 		d->seg_not_present = 1;
 		d->entry_number = GDT_ENTRY_TLS_MIN + i;
 		arch_get_user_desc(d);
+		builtin_memcpy(&ptls->desc[i], d, sizeof(user_desc_t));
 	}
+
+	free_compat_syscall_stack(syscall_mem);
 }
 
 #endif
diff --git a/criu/arch/x86/include/asm/restorer.h b/criu/arch/x86/include/asm/restorer.h
index c552fbdc0570..4a50e2342db0 100644
--- a/criu/arch/x86/include/asm/restorer.h
+++ b/criu/arch/x86/include/asm/restorer.h
@@ -5,25 +5,18 @@
 #include <compel/asm/fpu.h>
 #include "images/core.pb-c.h"
 #include <compel/plugins/std/syscall-codes.h>
-
 #include <compel/asm/sigframe.h>
+#include "asm/compat.h"
 
 #ifdef CONFIG_COMPAT
-extern void *alloc_compat_syscall_stack(void);
-extern void free_compat_syscall_stack(void *mem);
-extern unsigned long call32_from_64(void *stack, void *func);
 extern void restore_tls(tls_t *ptls);
-
 extern int arch_compat_rt_sigaction(void *stack32, int sig,
 		rt_sigaction_t_compat *act);
-#else
-static inline void *alloc_compat_syscall_stack(void) { return NULL; }
-static inline void free_compat_syscall_stack(void *stack32) { }
+#else /* CONFIG_COMPAT */
 static inline void restore_tls(tls_t *ptls) { }
 static inline int
 arch_compat_rt_sigaction(void *stack, int sig, void *act) { return -1; }
-#endif
-
+#endif /* !CONFIG_COMPAT */
 #ifdef CONFIG_X86_64
 
 #define RUN_CLONE_RESTORE_FN(ret, clone_flags, new_sp, parent_tid,      \
diff --git a/criu/arch/x86/sigaction_compat.c b/criu/arch/x86/sigaction_compat.c
index 076c014ef353..0e9e23bddbd3 100644
--- a/criu/arch/x86/sigaction_compat.c
+++ b/criu/arch/x86/sigaction_compat.c
@@ -1,14 +1,11 @@
 #include "asm/restorer.h"
 #include <compel/asm/fpu.h>
 #include "asm/string.h"
-
-#include <sys/mman.h>
+#include "asm/compat.h"
 
 #ifdef CR_NOGLIBC
 # include <compel/plugins/std/syscall.h>
 #else
-# define sys_mmap mmap
-# define sys_munmap munmap
 # ifndef  __NR32_rt_sigaction
 #  define  __NR32_rt_sigaction 174
 # endif
@@ -16,21 +13,6 @@
 #include "log.h"
 #include "cpu.h"
 
-void *alloc_compat_syscall_stack(void)
-{
-	void *mem = (void*)sys_mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
-			MAP_32BIT | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-
-	if (mem == MAP_FAILED)
-		return 0;
-	return mem;
-}
-
-void free_compat_syscall_stack(void *mem)
-{
-	sys_munmap(mem, PAGE_SIZE);
-}
-
 asm (	"	.pushsection .text				\n"
 	"	.global restore_rt_sigaction			\n"
 	"	.code32						\n"
-- 
2.10.2



More information about the CRIU mailing list