mirror of
https://github.com/torvalds/linux.git
synced 2024-11-29 15:41:36 +00:00
ARM: 9107/1: syscall: always store thread_info->abi_syscall
The system call number is used in a a couple of places, in particular ptrace, seccomp and /proc/<pid>/syscall. The last one apparently never worked reliably on ARM for tasks that are not currently getting traced. Storing the syscall number in the normal entry path makes it work, as well as allowing us to see if the current system call is for OABI compat mode, which is the next thing I want to hook into. Since the thread_info->syscall field is not just the number any more, it is now renamed to abi_syscall. In kernels that enable both OABI and EABI, the upper bits of this field encode 0x900000 (__NR_OABI_SYSCALL_BASE) for OABI tasks, while normal EABI tasks do not set the upper bits. This makes it possible to implement the in_oabi_syscall() helper later. All other users of thread_info->syscall go through the syscall_get_nr() helper, which in turn filters out the ABI bits. Note that the ABI information is lost with PTRACE_SET_SYSCALL, so one cannot set the internal number to a particular version, but this was already the case. We could change it to let gdb encode the ABI type along with the syscall in a CONFIG_OABI_COMPAT-enabled kernel, but that itself would be a (backwards-compatible) ABI change, so I don't do it here. Acked-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
This commit is contained in:
parent
b6e47f3c11
commit
4e57a4ddf6
@ -22,7 +22,10 @@ extern const unsigned long sys_call_table[];
|
||||
static inline int syscall_get_nr(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
return task_thread_info(task)->syscall;
|
||||
if (IS_ENABLED(CONFIG_AEABI) && !IS_ENABLED(CONFIG_OABI_COMPAT))
|
||||
return task_thread_info(task)->abi_syscall;
|
||||
|
||||
return task_thread_info(task)->abi_syscall & __NR_SYSCALL_MASK;
|
||||
}
|
||||
|
||||
static inline void syscall_rollback(struct task_struct *task,
|
||||
|
@ -62,7 +62,7 @@ struct thread_info {
|
||||
unsigned long stack_canary;
|
||||
#endif
|
||||
struct cpu_context_save cpu_context; /* cpu context */
|
||||
__u32 syscall; /* syscall number */
|
||||
__u32 abi_syscall; /* ABI type and syscall nr */
|
||||
__u8 used_cp[16]; /* thread used copro */
|
||||
unsigned long tp_value[2]; /* TLS registers */
|
||||
#ifdef CONFIG_CRUNCH
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define _UAPI__ASM_ARM_UNISTD_H
|
||||
|
||||
#define __NR_OABI_SYSCALL_BASE 0x900000
|
||||
#define __NR_SYSCALL_MASK 0x0fffff
|
||||
|
||||
#if defined(__thumb__) || defined(__ARM_EABI__)
|
||||
#define __NR_SYSCALL_BASE 0
|
||||
|
@ -48,6 +48,7 @@ int main(void)
|
||||
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
|
||||
DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain));
|
||||
DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context));
|
||||
DEFINE(TI_ABI_SYSCALL, offsetof(struct thread_info, abi_syscall));
|
||||
DEFINE(TI_USED_CP, offsetof(struct thread_info, used_cp));
|
||||
DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value));
|
||||
DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate));
|
||||
|
@ -226,6 +226,7 @@ ENTRY(vector_swi)
|
||||
/* saved_psr and saved_pc are now dead */
|
||||
|
||||
uaccess_disable tbl
|
||||
get_thread_info tsk
|
||||
|
||||
adr tbl, sys_call_table @ load syscall table pointer
|
||||
|
||||
@ -237,13 +238,17 @@ ENTRY(vector_swi)
|
||||
* get the old ABI syscall table address.
|
||||
*/
|
||||
bics r10, r10, #0xff000000
|
||||
strne r10, [tsk, #TI_ABI_SYSCALL]
|
||||
streq scno, [tsk, #TI_ABI_SYSCALL]
|
||||
eorne scno, r10, #__NR_OABI_SYSCALL_BASE
|
||||
ldrne tbl, =sys_oabi_call_table
|
||||
#elif !defined(CONFIG_AEABI)
|
||||
bic scno, scno, #0xff000000 @ mask off SWI op-code
|
||||
str scno, [tsk, #TI_ABI_SYSCALL]
|
||||
eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
|
||||
#else
|
||||
str scno, [tsk, #TI_ABI_SYSCALL]
|
||||
#endif
|
||||
get_thread_info tsk
|
||||
/*
|
||||
* Reload the registers that may have been corrupted on entry to
|
||||
* the syscall assembly (by tracing or context tracking.)
|
||||
@ -288,7 +293,6 @@ ENDPROC(vector_swi)
|
||||
* context switches, and waiting for our parent to respond.
|
||||
*/
|
||||
__sys_trace:
|
||||
mov r1, scno
|
||||
add r0, sp, #S_OFF
|
||||
bl syscall_trace_enter
|
||||
mov scno, r0
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <linux/tracehook.h>
|
||||
#include <linux/unistd.h>
|
||||
|
||||
#include <asm/syscall.h>
|
||||
#include <asm/traps.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
@ -811,7 +812,8 @@ long arch_ptrace(struct task_struct *child, long request,
|
||||
break;
|
||||
|
||||
case PTRACE_SET_SYSCALL:
|
||||
task_thread_info(child)->syscall = data;
|
||||
task_thread_info(child)->abi_syscall = data &
|
||||
__NR_SYSCALL_MASK;
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
@ -880,14 +882,14 @@ static void tracehook_report_syscall(struct pt_regs *regs,
|
||||
if (dir == PTRACE_SYSCALL_EXIT)
|
||||
tracehook_report_syscall_exit(regs, 0);
|
||||
else if (tracehook_report_syscall_entry(regs))
|
||||
current_thread_info()->syscall = -1;
|
||||
current_thread_info()->abi_syscall = -1;
|
||||
|
||||
regs->ARM_ip = ip;
|
||||
}
|
||||
|
||||
asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno)
|
||||
asmlinkage int syscall_trace_enter(struct pt_regs *regs)
|
||||
{
|
||||
current_thread_info()->syscall = scno;
|
||||
int scno;
|
||||
|
||||
if (test_thread_flag(TIF_SYSCALL_TRACE))
|
||||
tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
|
||||
@ -898,11 +900,11 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno)
|
||||
return -1;
|
||||
#else
|
||||
/* XXX: remove this once OABI gets fixed */
|
||||
secure_computing_strict(current_thread_info()->syscall);
|
||||
secure_computing_strict(syscall_get_nr(current, regs));
|
||||
#endif
|
||||
|
||||
/* Tracer or seccomp may have changed syscall. */
|
||||
scno = current_thread_info()->syscall;
|
||||
scno = syscall_get_nr(current, regs);
|
||||
|
||||
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
|
||||
trace_sys_enter(regs, scno);
|
||||
|
Loading…
Reference in New Issue
Block a user