Commit b0c5881d authored by Dmitry Safonov's avatar Dmitry Safonov Committed by Andrei Vagin

x86/compat: Use do_full_int80() instead of jump to ia32 mode

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: 's avatarAndrey Vagin <avagin@gmail.com>
Signed-off-by: 's avatarDmitry Safonov <dima@arista.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@gmail.com>
parent 9ec09471
......@@ -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 */
......
......@@ -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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment