Skip to content

Commit 4e57a4d

Browse files
arndbRussell King (Oracle)
authored andcommitted
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 <[email protected]> Signed-off-by: Arnd Bergmann <[email protected]> Signed-off-by: Russell King (Oracle) <[email protected]>
1 parent b6e47f3 commit 4e57a4d

File tree

6 files changed

+21
-10
lines changed

6 files changed

+21
-10
lines changed

arch/arm/include/asm/syscall.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ extern const unsigned long sys_call_table[];
2222
static inline int syscall_get_nr(struct task_struct *task,
2323
struct pt_regs *regs)
2424
{
25-
return task_thread_info(task)->syscall;
25+
if (IS_ENABLED(CONFIG_AEABI) && !IS_ENABLED(CONFIG_OABI_COMPAT))
26+
return task_thread_info(task)->abi_syscall;
27+
28+
return task_thread_info(task)->abi_syscall & __NR_SYSCALL_MASK;
2629
}
2730

2831
static inline void syscall_rollback(struct task_struct *task,

arch/arm/include/asm/thread_info.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ struct thread_info {
6262
unsigned long stack_canary;
6363
#endif
6464
struct cpu_context_save cpu_context; /* cpu context */
65-
__u32 syscall; /* syscall number */
65+
__u32 abi_syscall; /* ABI type and syscall nr */
6666
__u8 used_cp[16]; /* thread used copro */
6767
unsigned long tp_value[2]; /* TLS registers */
6868
#ifdef CONFIG_CRUNCH

arch/arm/include/uapi/asm/unistd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define _UAPI__ASM_ARM_UNISTD_H
1616

1717
#define __NR_OABI_SYSCALL_BASE 0x900000
18+
#define __NR_SYSCALL_MASK 0x0fffff
1819

1920
#if defined(__thumb__) || defined(__ARM_EABI__)
2021
#define __NR_SYSCALL_BASE 0

arch/arm/kernel/asm-offsets.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ int main(void)
4848
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
4949
DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain));
5050
DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context));
51+
DEFINE(TI_ABI_SYSCALL, offsetof(struct thread_info, abi_syscall));
5152
DEFINE(TI_USED_CP, offsetof(struct thread_info, used_cp));
5253
DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value));
5354
DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate));

arch/arm/kernel/entry-common.S

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ ENTRY(vector_swi)
226226
/* saved_psr and saved_pc are now dead */
227227

228228
uaccess_disable tbl
229+
get_thread_info tsk
229230

230231
adr tbl, sys_call_table @ load syscall table pointer
231232

@@ -237,13 +238,17 @@ ENTRY(vector_swi)
237238
* get the old ABI syscall table address.
238239
*/
239240
bics r10, r10, #0xff000000
241+
strne r10, [tsk, #TI_ABI_SYSCALL]
242+
streq scno, [tsk, #TI_ABI_SYSCALL]
240243
eorne scno, r10, #__NR_OABI_SYSCALL_BASE
241244
ldrne tbl, =sys_oabi_call_table
242245
#elif !defined(CONFIG_AEABI)
243246
bic scno, scno, #0xff000000 @ mask off SWI op-code
247+
str scno, [tsk, #TI_ABI_SYSCALL]
244248
eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
249+
#else
250+
str scno, [tsk, #TI_ABI_SYSCALL]
245251
#endif
246-
get_thread_info tsk
247252
/*
248253
* Reload the registers that may have been corrupted on entry to
249254
* the syscall assembly (by tracing or context tracking.)
@@ -288,7 +293,6 @@ ENDPROC(vector_swi)
288293
* context switches, and waiting for our parent to respond.
289294
*/
290295
__sys_trace:
291-
mov r1, scno
292296
add r0, sp, #S_OFF
293297
bl syscall_trace_enter
294298
mov scno, r0

arch/arm/kernel/ptrace.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/tracehook.h>
2626
#include <linux/unistd.h>
2727

28+
#include <asm/syscall.h>
2829
#include <asm/traps.h>
2930

3031
#define CREATE_TRACE_POINTS
@@ -811,7 +812,8 @@ long arch_ptrace(struct task_struct *child, long request,
811812
break;
812813

813814
case PTRACE_SET_SYSCALL:
814-
task_thread_info(child)->syscall = data;
815+
task_thread_info(child)->abi_syscall = data &
816+
__NR_SYSCALL_MASK;
815817
ret = 0;
816818
break;
817819

@@ -880,14 +882,14 @@ static void tracehook_report_syscall(struct pt_regs *regs,
880882
if (dir == PTRACE_SYSCALL_EXIT)
881883
tracehook_report_syscall_exit(regs, 0);
882884
else if (tracehook_report_syscall_entry(regs))
883-
current_thread_info()->syscall = -1;
885+
current_thread_info()->abi_syscall = -1;
884886

885887
regs->ARM_ip = ip;
886888
}
887889

888-
asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno)
890+
asmlinkage int syscall_trace_enter(struct pt_regs *regs)
889891
{
890-
current_thread_info()->syscall = scno;
892+
int scno;
891893

892894
if (test_thread_flag(TIF_SYSCALL_TRACE))
893895
tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
@@ -898,11 +900,11 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno)
898900
return -1;
899901
#else
900902
/* XXX: remove this once OABI gets fixed */
901-
secure_computing_strict(current_thread_info()->syscall);
903+
secure_computing_strict(syscall_get_nr(current, regs));
902904
#endif
903905

904906
/* Tracer or seccomp may have changed syscall. */
905-
scno = current_thread_info()->syscall;
907+
scno = syscall_get_nr(current, regs);
906908

907909
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
908910
trace_sys_enter(regs, scno);

0 commit comments

Comments
 (0)