diff --git a/criu/arch/x86/include/asm/compat.h b/criu/arch/x86/include/asm/compat.h new file mode 100644 index 000000000..8379af452 --- /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 +# include +#else +# define sys_mmap mmap +# define sys_munmap munmap +#endif + +#include + +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 302b412af..2385ec16d 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 +#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 e5636aef5..2dc4fe1b7 100644 --- a/criu/arch/x86/include/asm/restorer.h +++ b/criu/arch/x86/include/asm/restorer.h @@ -5,25 +5,18 @@ #include #include "images/core.pb-c.h" #include - #include +#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, \ thread_args, clone_restore_fn) \ diff --git a/criu/arch/x86/sigaction_compat.c b/criu/arch/x86/sigaction_compat.c index 076c014ef..0e9e23bdd 100644 --- a/criu/arch/x86/sigaction_compat.c +++ b/criu/arch/x86/sigaction_compat.c @@ -1,14 +1,11 @@ #include "asm/restorer.h" #include #include "asm/string.h" - -#include +#include "asm/compat.h" #ifdef CR_NOGLIBC # include #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"