wrong syscall number and OABI syscall is used for syscall re…

Top Page
Message as email
+ (text/plain)
+ diff (application/octet-stream)
Delete this message
Reply to this message
Author: Yauheni Kaliuta
To: linux-arm-kernel
Subject: wrong syscall number and OABI syscall is used for syscall restarting when EABI is enabled

The problem is in the code of syscall restarting after interrupting
with signal.

arch/arm/kernel/signal.c, do_signal()

The mechanism of the restarting is following:

the kernel puts a piece of code (to execute syscall "restart_syscall",
number 0) in the userspace's stack and points the userspace's PC to
this code:

                regs->ARM_sp -= 12;
                usp = (u32 __user *)regs->ARM_sp;

                put_user(regs->ARM_pc, &usp[0]);
                /* swi __NR_restart_syscall */
                put_user(0xef000000 | __NR_restart_syscall, &usp[1]);
                /* ldr    pc, [sp], #12 */
                put_user(0xe49df00c, &usp[2]);

                flush_icache_range((unsigned long)usp,
                           (unsigned long)(usp + 3));

                regs->ARM_pc = regs->ARM_sp + 4;

This code knows nothing about EABI (it uses OABI syscall,
swi <syscall number>, but EABI uses r7 for syscall number and swi 0x0
for syscall calling).

In case of EABI-enabled system when we use OABI-compat syscall we
have __NR_restart_syscall is 0, and r7 from the userspace. vector_swi
code sees the EABI syscall and tries to use r7 as a syscall number, so
we are trapping to bad_syscall() which generates SIGILL.

I'm attaching a fix for EABI+OABI-comat system. For EABI only system
it should be improved to store and recover userspace's R7 and pass
r7=__NR_restart_syscall to swi 0.