[CRIU] [PATCH 2/3] x86/compat: Use do_full_int80() instead of jump to ia32 mode
Dmitry Safonov
dima at arista.com
Wed Oct 31 01:35:30 MSK 2018
Kernel will send signal with ABI of *syscall* that made rt_sigacation().
In sigaction_compat_abi():
> if (in_ia32_syscall())
> act->sa.sa_flags |= SA_IA32_ABI;
So, we can omit switching to ia32 mode and just call int80 like in other places.
We still need 32-bit argument for syscall (sig action pointer).
As call32_from_64() switches mode, it's .text should be placed in lower 4Gb,
which was the reason of segfault if linker places criu code above 4Gb.
Oops, my bad.
Fixes: #567
Reported-by: Andrey Vagin <avagin at gmail.com>
Signed-off-by: Dmitry Safonov <dima at arista.com>
---
criu/arch/x86/call32.S | 7 +++++++
criu/arch/x86/sigaction_compat.c | 18 ++++++++++++++----
2 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/criu/arch/x86/call32.S b/criu/arch/x86/call32.S
index c2ddd9fc2682..8c32c4f7a3d6 100644
--- a/criu/arch/x86/call32.S
+++ b/criu/arch/x86/call32.S
@@ -23,6 +23,13 @@
/*
* @rdi: Stack to use
* @esi: Pointer to function for calling
+ *
+ * Note: .code32 in this function doesn't guarantee that is will
+ * be place under 4GB by linker.
+ * Linker script would guarantee that, but it would break
+ * -fpie address randomization. In the end, the caller is
+ * responible for placing/checking that the code is
+ * accessible in 32-bit mode.
*/
ENTRY(call32_from_64)
/* Callee-saving registers due to ABI */
diff --git a/criu/arch/x86/sigaction_compat.c b/criu/arch/x86/sigaction_compat.c
index 5965ef79fabe..b38ba8011889 100644
--- a/criu/arch/x86/sigaction_compat.c
+++ b/criu/arch/x86/sigaction_compat.c
@@ -29,17 +29,27 @@ extern char restore_rt_sigaction;
int arch_compat_rt_sigaction(void *stack32, int sig, rt_sigaction_t_compat *act)
{
int ret;
+ struct syscall_args32 arg = {};
+ unsigned long act_stack = (unsigned long)stack32;
+
+ /* To make sure the 32-bit stack was allocated in caller */
+ if (act_stack >= (uint32_t)-1) {
+ pr_err("compat rt_sigaction without 32-bit stack\n");
+ return -1;
+ }
/*
* To be sure, that sigaction pointer lies under 4G,
* coping it on the bottom of the stack.
*/
memcpy(stack32, act, sizeof(rt_sigaction_t_compat));
+ arg.nr = __NR32_rt_sigaction;
+ arg.arg0 = sig;
+ arg.arg1 = (uint32_t)act_stack; /* act */
+ arg.arg2 = 0; /* oldact */
+ arg.arg3 = (uint32_t)sizeof(act->rt_sa_mask); /* sigsetsize */
- asm volatile ("\t movl %%ebx,%%ebx\n" : :"b"(sig)); /* signum */
- asm volatile ("\t movl %%ecx,%%ecx\n" : :"c"(stack32)); /* act */
- asm volatile ("\t movl %%edx,%%edx\n" : :"d"(sizeof(act->rt_sa_mask)));
- call32_from_64(stack32 + PAGE_SIZE, &restore_rt_sigaction);
+ do_full_int80(&arg);
asm volatile ("\t movl %%eax,%0\n" : "=r"(ret));
return ret;
}
--
2.19.1
More information about the CRIU
mailing list