From fa697140f9a20119a9ec8fd7460cc4314fbdaff3 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Thu, 5 Apr 2018 11:53:02 +0200 Subject: syscalls/x86: Use 'struct pt_regs' based syscall calling convention for 64-bit syscalls Let's make use of ARCH_HAS_SYSCALL_WRAPPER=y on pure 64-bit x86-64 systems: Each syscall defines a stub which takes struct pt_regs as its only argument. It decodes just those parameters it needs, e.g: asmlinkage long sys_xyzzy(const struct pt_regs *regs) { return SyS_xyzzy(regs->di, regs->si, regs->dx); } This approach avoids leaking random user-provided register content down the call chain. For example, for sys_recv() which is a 4-parameter syscall, the assembly now is (in slightly reordered fashion): : callq <__fentry__> /* decode regs->di, ->si, ->dx and ->r10 */ mov 0x70(%rdi),%rdi mov 0x68(%rdi),%rsi mov 0x60(%rdi),%rdx mov 0x38(%rdi),%rcx [ SyS_recv() is automatically inlined by the compiler, as it is not [yet] used anywhere else ] /* clear %r9 and %r8, the 5th and 6th args */ xor %r9d,%r9d xor %r8d,%r8d /* do the actual work */ callq __sys_recvfrom /* cleanup and return */ cltq retq The only valid place in an x86-64 kernel which rightfully calls a syscall function on its own -- vsyscall -- needs to be modified to pass struct pt_regs onwards as well. To keep the syscall table generation working independent of SYSCALL_PTREGS being enabled, the stubs are named the same as the "original" syscall stubs, i.e. sys_*(). This patch is based on an original proof-of-concept | From: Linus Torvalds | Signed-off-by: Linus Torvalds and was split up and heavily modified by me, in particular to base it on ARCH_HAS_SYSCALL_WRAPPER, to limit it to 64-bit-only for the time being, and to update the vsyscall to the new calling convention. Signed-off-by: Dominik Brodowski Acked-by: Linus Torvalds Cc: Al Viro Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20180405095307.3730-4-linux@dominikbrodowski.net Signed-off-by: Ingo Molnar --- arch/x86/include/asm/syscall_wrapper.h | 70 ++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 arch/x86/include/asm/syscall_wrapper.h (limited to 'arch/x86/include/asm/syscall_wrapper.h') diff --git a/arch/x86/include/asm/syscall_wrapper.h b/arch/x86/include/asm/syscall_wrapper.h new file mode 100644 index 000000000000..702bdee377af --- /dev/null +++ b/arch/x86/include/asm/syscall_wrapper.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * syscall_wrapper.h - x86 specific wrappers to syscall definitions + */ + +#ifndef _ASM_X86_SYSCALL_WRAPPER_H +#define _ASM_X86_SYSCALL_WRAPPER_H + +/* + * Instead of the generic __SYSCALL_DEFINEx() definition, this macro takes + * struct pt_regs *regs as the only argument of the syscall stub named + * sys_*(). It decodes just the registers it needs and passes them on to + * the SyS_*() wrapper and then to the SYSC_*() function doing the actual job. + * These wrappers and functions are inlined, meaning that the assembly looks + * as follows (slightly re-ordered): + * + * : <-- syscall with 4 parameters + * callq <__fentry__> + * + * mov 0x70(%rdi),%rdi <-- decode regs->di + * mov 0x68(%rdi),%rsi <-- decode regs->si + * mov 0x60(%rdi),%rdx <-- decode regs->dx + * mov 0x38(%rdi),%rcx <-- decode regs->r10 + * + * xor %r9d,%r9d <-- clear %r9 + * xor %r8d,%r8d <-- clear %r8 + * + * callq __sys_recvfrom <-- do the actual work in __sys_recvfrom() + * which takes 6 arguments + * + * cltq <-- extend return value to 64-bit + * retq <-- return + * + * This approach avoids leaking random user-provided register content down + * the call chain. + * + * As the generic SYSCALL_DEFINE0() macro does not decode any parameters for + * obvious reasons, and passing struct pt_regs *regs to it in %rdi does not + * hurt, there is no need to override it. + */ +#define __SYSCALL_DEFINEx(x, name, ...) \ + asmlinkage long sys##name(const struct pt_regs *regs); \ + ALLOW_ERROR_INJECTION(sys##name, ERRNO); \ + static long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ + static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ + asmlinkage long sys##name(const struct pt_regs *regs) \ + { \ + return SyS##name(__MAP(x,__SC_ARGS \ + ,,regs->di,,regs->si,,regs->dx \ + ,,regs->r10,,regs->r8,,regs->r9)); \ + } \ + static long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ + { \ + long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ + __MAP(x,__SC_TEST,__VA_ARGS__); \ + __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ + return ret; \ + } \ + static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)) + +/* + * For VSYSCALLS, we need to declare these three syscalls with the new + * pt_regs-based calling convention for in-kernel use. + */ +struct pt_regs; +asmlinkage long sys_getcpu(const struct pt_regs *regs); /* di,si,dx */ +asmlinkage long sys_gettimeofday(const struct pt_regs *regs); /* di,si */ +asmlinkage long sys_time(const struct pt_regs *regs); /* di */ + +#endif /* _ASM_X86_SYSCALL_WRAPPER_H */ -- cgit v1.2.1 From ebeb8c82ffaf94435806ff0b686fffd41dd410b5 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Thu, 5 Apr 2018 11:53:04 +0200 Subject: syscalls/x86: Use 'struct pt_regs' based syscall calling for IA32_EMULATION and x32 Extend ARCH_HAS_SYSCALL_WRAPPER for i386 emulation and for x32 on 64-bit x86. For x32, all we need to do is to create an additional stub for each compat syscall which decodes the parameters in x86-64 ordering, e.g.: asmlinkage long __compat_sys_x32_xyzzy(struct pt_regs *regs) { return c_SyS_xyzzy(regs->di, regs->si, regs->dx); } For i386 emulation, we need to teach compat_sys_*() to take struct pt_regs as its only argument, e.g.: asmlinkage long __compat_sys_ia32_xyzzy(struct pt_regs *regs) { return c_SyS_xyzzy(regs->bx, regs->cx, regs->dx); } In addition, we need to create additional stubs for common syscalls (that is, for syscalls which have the same parameters on 32-bit and 64-bit), e.g.: asmlinkage long __sys_ia32_xyzzy(struct pt_regs *regs) { return c_sys_xyzzy(regs->bx, regs->cx, regs->dx); } This approach avoids leaking random user-provided register content down the call chain. This patch is based on an original proof-of-concept | From: Linus Torvalds | Signed-off-by: Linus Torvalds and was split up and heavily modified by me, in particular to base it on ARCH_HAS_SYSCALL_WRAPPER. Signed-off-by: Dominik Brodowski Acked-by: Linus Torvalds Cc: Al Viro Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20180405095307.3730-6-linux@dominikbrodowski.net Signed-off-by: Ingo Molnar --- arch/x86/include/asm/syscall_wrapper.h | 117 +++++++++++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 4 deletions(-) (limited to 'arch/x86/include/asm/syscall_wrapper.h') diff --git a/arch/x86/include/asm/syscall_wrapper.h b/arch/x86/include/asm/syscall_wrapper.h index 702bdee377af..49d7e4970110 100644 --- a/arch/x86/include/asm/syscall_wrapper.h +++ b/arch/x86/include/asm/syscall_wrapper.h @@ -6,6 +6,111 @@ #ifndef _ASM_X86_SYSCALL_WRAPPER_H #define _ASM_X86_SYSCALL_WRAPPER_H +/* Mapping of registers to parameters for syscalls on x86-64 and x32 */ +#define SC_X86_64_REGS_TO_ARGS(x, ...) \ + __MAP(x,__SC_ARGS \ + ,,regs->di,,regs->si,,regs->dx \ + ,,regs->r10,,regs->r8,,regs->r9) \ + +/* Mapping of registers to parameters for syscalls on i386 */ +#define SC_IA32_REGS_TO_ARGS(x, ...) \ + __MAP(x,__SC_ARGS \ + ,,(unsigned int)regs->bx,,(unsigned int)regs->cx \ + ,,(unsigned int)regs->dx,,(unsigned int)regs->si \ + ,,(unsigned int)regs->di,,(unsigned int)regs->bp) + +#ifdef CONFIG_IA32_EMULATION +/* + * For IA32 emulation, we need to handle "compat" syscalls *and* create + * additional wrappers (aptly named __sys_ia32_sys_xyzzy) which decode the + * ia32 regs in the proper order for shared or "common" syscalls. As some + * syscalls may not be implemented, we need to expand COND_SYSCALL in + * kernel/sys_ni.c and SYS_NI in kernel/time/posix-stubs.c to cover this + * case as well. + */ +#define COMPAT_SC_IA32_STUBx(x, name, ...) \ + asmlinkage long __compat_sys_ia32##name(const struct pt_regs *regs);\ + ALLOW_ERROR_INJECTION(__compat_sys_ia32##name, ERRNO); \ + asmlinkage long __compat_sys_ia32##name(const struct pt_regs *regs)\ + { \ + return c_SyS##name(SC_IA32_REGS_TO_ARGS(x,__VA_ARGS__));\ + } \ + +#define SC_IA32_WRAPPERx(x, name, ...) \ + asmlinkage long __sys_ia32##name(const struct pt_regs *regs); \ + ALLOW_ERROR_INJECTION(__sys_ia32##name, ERRNO); \ + asmlinkage long __sys_ia32##name(const struct pt_regs *regs) \ + { \ + return SyS##name(SC_IA32_REGS_TO_ARGS(x,__VA_ARGS__)); \ + } + +#define COND_SYSCALL(name) \ + cond_syscall(sys_##name); \ + cond_syscall(__sys_ia32_##name) + +#define SYS_NI(name) \ + SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers); \ + SYSCALL_ALIAS(__sys_ia32_##name, sys_ni_posix_timers) + +#else /* CONFIG_IA32_EMULATION */ +#define COMPAT_SC_IA32_STUBx(x, name, ...) +#define SC_IA32_WRAPPERx(x, fullname, name, ...) +#endif /* CONFIG_IA32_EMULATION */ + + +#ifdef CONFIG_X86_X32 +/* + * For the x32 ABI, we need to create a stub for compat_sys_*() which is aware + * of the x86-64-style parameter ordering of x32 syscalls. The syscalls common + * with x86_64 obviously do not need such care. + */ +#define COMPAT_SC_X32_STUBx(x, name, ...) \ + asmlinkage long __compat_sys_x32##name(const struct pt_regs *regs);\ + ALLOW_ERROR_INJECTION(__compat_sys_x32##name, ERRNO); \ + asmlinkage long __compat_sys_x32##name(const struct pt_regs *regs)\ + { \ + return c_SyS##name(SC_X86_64_REGS_TO_ARGS(x,__VA_ARGS__));\ + } \ + +#else /* CONFIG_X86_X32 */ +#define COMPAT_SC_X32_STUBx(x, name, ...) +#endif /* CONFIG_X86_X32 */ + + +#ifdef CONFIG_COMPAT +/* + * Compat means IA32_EMULATION and/or X86_X32. As they use a different + * mapping of registers to parameters, we need to generate stubs for each + * of them. There is no need to implement COMPAT_SYSCALL_DEFINE0, as it is + * unused on x86. + */ +#define COMPAT_SYSCALL_DEFINEx(x, name, ...) \ + static long c_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ + static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ + COMPAT_SC_IA32_STUBx(x, name, __VA_ARGS__) \ + COMPAT_SC_X32_STUBx(x, name, __VA_ARGS__) \ + static long c_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ + { \ + return C_SYSC##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__)); \ + } \ + static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)) + +/* + * As some compat syscalls may not be implemented, we need to expand + * COND_SYSCALL_COMPAT in kernel/sys_ni.c and COMPAT_SYS_NI in + * kernel/time/posix-stubs.c to cover this case as well. + */ +#define COND_SYSCALL_COMPAT(name) \ + cond_syscall(__compat_sys_ia32_##name); \ + cond_syscall(__compat_sys_x32_##name) + +#define COMPAT_SYS_NI(name) \ + SYSCALL_ALIAS(__compat_sys_ia32_##name, sys_ni_posix_timers); \ + SYSCALL_ALIAS(__compat_sys_x32_##name, sys_ni_posix_timers) + +#endif /* CONFIG_COMPAT */ + + /* * Instead of the generic __SYSCALL_DEFINEx() definition, this macro takes * struct pt_regs *regs as the only argument of the syscall stub named @@ -34,9 +139,14 @@ * This approach avoids leaking random user-provided register content down * the call chain. * + * If IA32_EMULATION is enabled, this macro generates an additional wrapper + * named __sys_ia32_*() which decodes the struct pt_regs *regs according + * to the i386 calling convention (bx, cx, dx, si, di, bp). + * * As the generic SYSCALL_DEFINE0() macro does not decode any parameters for * obvious reasons, and passing struct pt_regs *regs to it in %rdi does not - * hurt, there is no need to override it. + * hurt, there is no need to override it, or to define it differently for + * IA32_EMULATION. */ #define __SYSCALL_DEFINEx(x, name, ...) \ asmlinkage long sys##name(const struct pt_regs *regs); \ @@ -45,10 +155,9 @@ static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ asmlinkage long sys##name(const struct pt_regs *regs) \ { \ - return SyS##name(__MAP(x,__SC_ARGS \ - ,,regs->di,,regs->si,,regs->dx \ - ,,regs->r10,,regs->r8,,regs->r9)); \ + return SyS##name(SC_X86_64_REGS_TO_ARGS(x,__VA_ARGS__));\ } \ + SC_IA32_WRAPPERx(x, name, __VA_ARGS__) \ static long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ { \ long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ -- cgit v1.2.1 From e145242ea0df6b7d28fd7186e61d6840fa4bb06e Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Mon, 9 Apr 2018 12:51:42 +0200 Subject: syscalls/core, syscalls/x86: Clean up syscall stub naming convention Tidy the naming convention for compat syscall subs. Hints which describe the purpose of the stub go in front and receive a double underscore to denote that they are generated on-the-fly by the SYSCALL_DEFINEx() macro. For the generic case, this means (0xffffffff prefix removed): 810f08d0 t kernel_waitid # common C function (see kernel/exit.c) __do_sys_waitid # inlined helper doing the actual work # (takes original parameters as declared) 810f1aa0 T __se_sys_waitid # sign-extending C function calling inlined # helper (takes parameters of type long; # casts them to the declared type) 810f1aa0 T sys_waitid # alias to __se_sys_waitid() (taking # parameters as declared), to be included # in syscall table For x86, the naming is as follows: 810efc70 t kernel_waitid # common C function (see kernel/exit.c) __do_sys_waitid # inlined helper doing the actual work # (takes original parameters as declared) 810efd60 t __se_sys_waitid # sign-extending C function calling inlined # helper (takes parameters of type long; # casts them to the declared type) 810f1140 T __ia32_sys_waitid # IA32_EMULATION 32-bit-ptregs -> C stub, # calls __se_sys_waitid(); to be included # in syscall table 810f1110 T sys_waitid # x86 64-bit-ptregs -> C stub, calls # __se_sys_waitid(); to be included in # syscall table For x86, sys_waitid() will be re-named to __x64_sys_waitid in a follow-up patch. Suggested-by: Ingo Molnar Signed-off-by: Dominik Brodowski Cc: Al Viro Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20180409105145.5364-2-linux@dominikbrodowski.net Signed-off-by: Ingo Molnar --- arch/x86/include/asm/syscall_wrapper.h | 35 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'arch/x86/include/asm/syscall_wrapper.h') diff --git a/arch/x86/include/asm/syscall_wrapper.h b/arch/x86/include/asm/syscall_wrapper.h index 49d7e4970110..798a3c2bff4f 100644 --- a/arch/x86/include/asm/syscall_wrapper.h +++ b/arch/x86/include/asm/syscall_wrapper.h @@ -22,7 +22,7 @@ #ifdef CONFIG_IA32_EMULATION /* * For IA32 emulation, we need to handle "compat" syscalls *and* create - * additional wrappers (aptly named __sys_ia32_sys_xyzzy) which decode the + * additional wrappers (aptly named __ia32_sys_xyzzy) which decode the * ia32 regs in the proper order for shared or "common" syscalls. As some * syscalls may not be implemented, we need to expand COND_SYSCALL in * kernel/sys_ni.c and SYS_NI in kernel/time/posix-stubs.c to cover this @@ -37,20 +37,20 @@ } \ #define SC_IA32_WRAPPERx(x, name, ...) \ - asmlinkage long __sys_ia32##name(const struct pt_regs *regs); \ - ALLOW_ERROR_INJECTION(__sys_ia32##name, ERRNO); \ - asmlinkage long __sys_ia32##name(const struct pt_regs *regs) \ + asmlinkage long __ia32_sys##name(const struct pt_regs *regs); \ + ALLOW_ERROR_INJECTION(__ia32_sys##name, ERRNO); \ + asmlinkage long __ia32_sys##name(const struct pt_regs *regs) \ { \ - return SyS##name(SC_IA32_REGS_TO_ARGS(x,__VA_ARGS__)); \ + return __se_sys##name(SC_IA32_REGS_TO_ARGS(x,__VA_ARGS__));\ } #define COND_SYSCALL(name) \ cond_syscall(sys_##name); \ - cond_syscall(__sys_ia32_##name) + cond_syscall(__ia32_sys_##name) #define SYS_NI(name) \ SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers); \ - SYSCALL_ALIAS(__sys_ia32_##name, sys_ni_posix_timers) + SYSCALL_ALIAS(__ia32_sys_##name, sys_ni_posix_timers) #else /* CONFIG_IA32_EMULATION */ #define COMPAT_SC_IA32_STUBx(x, name, ...) @@ -115,9 +115,10 @@ * Instead of the generic __SYSCALL_DEFINEx() definition, this macro takes * struct pt_regs *regs as the only argument of the syscall stub named * sys_*(). It decodes just the registers it needs and passes them on to - * the SyS_*() wrapper and then to the SYSC_*() function doing the actual job. - * These wrappers and functions are inlined, meaning that the assembly looks - * as follows (slightly re-ordered): + * the __se_sys_*() wrapper performing sign extension and then to the + * __do_sys_*() function doing the actual job. These wrappers and functions + * are inlined (at least in very most cases), meaning that the assembly looks + * as follows (slightly re-ordered for better readability): * * : <-- syscall with 4 parameters * callq <__fentry__> @@ -140,7 +141,7 @@ * the call chain. * * If IA32_EMULATION is enabled, this macro generates an additional wrapper - * named __sys_ia32_*() which decodes the struct pt_regs *regs according + * named __ia32_sys_*() which decodes the struct pt_regs *regs according * to the i386 calling convention (bx, cx, dx, si, di, bp). * * As the generic SYSCALL_DEFINE0() macro does not decode any parameters for @@ -151,21 +152,21 @@ #define __SYSCALL_DEFINEx(x, name, ...) \ asmlinkage long sys##name(const struct pt_regs *regs); \ ALLOW_ERROR_INJECTION(sys##name, ERRNO); \ - static long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ - static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ + static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ + static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ asmlinkage long sys##name(const struct pt_regs *regs) \ { \ - return SyS##name(SC_X86_64_REGS_TO_ARGS(x,__VA_ARGS__));\ + return __se_sys##name(SC_X86_64_REGS_TO_ARGS(x,__VA_ARGS__));\ } \ SC_IA32_WRAPPERx(x, name, __VA_ARGS__) \ - static long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ + static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ { \ - long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ + long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\ __MAP(x,__SC_TEST,__VA_ARGS__); \ __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ return ret; \ } \ - static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)) + static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) /* * For VSYSCALLS, we need to declare these three syscalls with the new -- cgit v1.2.1 From 5ac9efa3c50d7caff9f3933bb8a3ad1139d92d92 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Mon, 9 Apr 2018 12:51:43 +0200 Subject: syscalls/core, syscalls/x86: Clean up compat syscall stub naming convention Tidy the naming convention for compat syscall subs. Hints which describe the purpose of the stub go in front and receive a double underscore to denote that they are generated on-the-fly by the COMPAT_SYSCALL_DEFINEx() macro. For the generic case, this means: t kernel_waitid # common C function (see kernel/exit.c) __do_compat_sys_waitid # inlined helper doing the actual work # (takes original parameters as declared) T __se_compat_sys_waitid # sign-extending C function calling inlined # helper (takes parameters of type long, # casts them to unsigned long and then to # the declared type) T compat_sys_waitid # alias to __se_compat_sys_waitid() # (taking parameters as declared), to # be included in syscall table For x86, the naming is as follows: t kernel_waitid # common C function (see kernel/exit.c) __do_compat_sys_waitid # inlined helper doing the actual work # (takes original parameters as declared) t __se_compat_sys_waitid # sign-extending C function calling inlined # helper (takes parameters of type long, # casts them to unsigned long and then to # the declared type) T __ia32_compat_sys_waitid # IA32_EMULATION 32-bit-ptregs -> C stub, # calls __se_compat_sys_waitid(); to be # included in syscall table T __x32_compat_sys_waitid # x32 64-bit-ptregs -> C stub, calls # __se_compat_sys_waitid(); to be included # in syscall table If only one of IA32_EMULATION and x32 is enabled, __se_compat_sys_waitid() may be inlined into the stub __{ia32,x32}_compat_sys_waitid(). Suggested-by: Ingo Molnar Signed-off-by: Dominik Brodowski Cc: Al Viro Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20180409105145.5364-3-linux@dominikbrodowski.net Signed-off-by: Ingo Molnar --- arch/x86/include/asm/syscall_wrapper.h | 44 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'arch/x86/include/asm/syscall_wrapper.h') diff --git a/arch/x86/include/asm/syscall_wrapper.h b/arch/x86/include/asm/syscall_wrapper.h index 798a3c2bff4f..8d0951cfc2d4 100644 --- a/arch/x86/include/asm/syscall_wrapper.h +++ b/arch/x86/include/asm/syscall_wrapper.h @@ -29,11 +29,11 @@ * case as well. */ #define COMPAT_SC_IA32_STUBx(x, name, ...) \ - asmlinkage long __compat_sys_ia32##name(const struct pt_regs *regs);\ - ALLOW_ERROR_INJECTION(__compat_sys_ia32##name, ERRNO); \ - asmlinkage long __compat_sys_ia32##name(const struct pt_regs *regs)\ + asmlinkage long __ia32_compat_sys##name(const struct pt_regs *regs);\ + ALLOW_ERROR_INJECTION(__ia32_compat_sys##name, ERRNO); \ + asmlinkage long __ia32_compat_sys##name(const struct pt_regs *regs)\ { \ - return c_SyS##name(SC_IA32_REGS_TO_ARGS(x,__VA_ARGS__));\ + return __se_compat_sys##name(SC_IA32_REGS_TO_ARGS(x,__VA_ARGS__));\ } \ #define SC_IA32_WRAPPERx(x, name, ...) \ @@ -65,11 +65,11 @@ * with x86_64 obviously do not need such care. */ #define COMPAT_SC_X32_STUBx(x, name, ...) \ - asmlinkage long __compat_sys_x32##name(const struct pt_regs *regs);\ - ALLOW_ERROR_INJECTION(__compat_sys_x32##name, ERRNO); \ - asmlinkage long __compat_sys_x32##name(const struct pt_regs *regs)\ + asmlinkage long __x32_compat_sys##name(const struct pt_regs *regs);\ + ALLOW_ERROR_INJECTION(__x32_compat_sys##name, ERRNO); \ + asmlinkage long __x32_compat_sys##name(const struct pt_regs *regs)\ { \ - return c_SyS##name(SC_X86_64_REGS_TO_ARGS(x,__VA_ARGS__));\ + return __se_compat_sys##name(SC_X86_64_REGS_TO_ARGS(x,__VA_ARGS__));\ } \ #else /* CONFIG_X86_X32 */ @@ -84,16 +84,16 @@ * of them. There is no need to implement COMPAT_SYSCALL_DEFINE0, as it is * unused on x86. */ -#define COMPAT_SYSCALL_DEFINEx(x, name, ...) \ - static long c_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ - static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ - COMPAT_SC_IA32_STUBx(x, name, __VA_ARGS__) \ - COMPAT_SC_X32_STUBx(x, name, __VA_ARGS__) \ - static long c_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ - { \ - return C_SYSC##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__)); \ - } \ - static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)) +#define COMPAT_SYSCALL_DEFINEx(x, name, ...) \ + static long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ + static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ + COMPAT_SC_IA32_STUBx(x, name, __VA_ARGS__) \ + COMPAT_SC_X32_STUBx(x, name, __VA_ARGS__) \ + static long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ + { \ + return __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__));\ + } \ + static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) /* * As some compat syscalls may not be implemented, we need to expand @@ -101,12 +101,12 @@ * kernel/time/posix-stubs.c to cover this case as well. */ #define COND_SYSCALL_COMPAT(name) \ - cond_syscall(__compat_sys_ia32_##name); \ - cond_syscall(__compat_sys_x32_##name) + cond_syscall(__ia32_compat_sys_##name); \ + cond_syscall(__x32_compat_sys_##name) #define COMPAT_SYS_NI(name) \ - SYSCALL_ALIAS(__compat_sys_ia32_##name, sys_ni_posix_timers); \ - SYSCALL_ALIAS(__compat_sys_x32_##name, sys_ni_posix_timers) + SYSCALL_ALIAS(__ia32_compat_sys_##name, sys_ni_posix_timers); \ + SYSCALL_ALIAS(__x32_compat_sys_##name, sys_ni_posix_timers) #endif /* CONFIG_COMPAT */ -- cgit v1.2.1 From d5a00528b58cdb2c71206e18bd021e34c4eab878 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Mon, 9 Apr 2018 12:51:44 +0200 Subject: syscalls/core, syscalls/x86: Rename struct pt_regs-based sys_*() to __x64_sys_*() This rename allows us to have a coherent syscall stub naming convention on 64-bit x86 (0xffffffff prefix removed): 810f0af0 t kernel_waitid # common (32/64) kernel helper __do_sys_waitid # inlined helper doing actual work 810f0be0 t __se_sys_waitid # C func calling inlined helper __do_compat_sys_waitid # inlined helper doing actual work 810f0d80 t __se_compat_sys_waitid # compat C func calling inlined helper 810f2080 T __x64_sys_waitid # x64 64-bit-ptregs -> C stub 810f20b0 T __ia32_sys_waitid # ia32 32-bit-ptregs -> C stub[*] 810f2470 T __ia32_compat_sys_waitid # ia32 32-bit-ptregs -> compat C stub 810f2490 T __x32_compat_sys_waitid # x32 64-bit-ptregs -> compat C stub [*] This stub is unused, as the syscall table links __ia32_compat_sys_waitid instead of __ia32_sys_waitid as we need a compat variant here. Suggested-by: Ingo Molnar Signed-off-by: Dominik Brodowski Cc: Al Viro Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20180409105145.5364-4-linux@dominikbrodowski.net Signed-off-by: Ingo Molnar --- arch/x86/include/asm/syscall_wrapper.h | 63 +++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 17 deletions(-) (limited to 'arch/x86/include/asm/syscall_wrapper.h') diff --git a/arch/x86/include/asm/syscall_wrapper.h b/arch/x86/include/asm/syscall_wrapper.h index 8d0951cfc2d4..a598013e08e9 100644 --- a/arch/x86/include/asm/syscall_wrapper.h +++ b/arch/x86/include/asm/syscall_wrapper.h @@ -44,12 +44,23 @@ return __se_sys##name(SC_IA32_REGS_TO_ARGS(x,__VA_ARGS__));\ } +/* + * To keep the naming coherent, re-define SYSCALL_DEFINE0 to create an alias + * named __ia32_sys_*() + */ +#define SYSCALL_DEFINE0(sname) \ + SYSCALL_METADATA(_##sname, 0); \ + asmlinkage long __x64_sys_##sname(void); \ + ALLOW_ERROR_INJECTION(__x64_sys_##sname, ERRNO); \ + SYSCALL_ALIAS(__ia32_sys_##sname, __x64_sys_##sname); \ + asmlinkage long __x64_sys_##sname(void) + #define COND_SYSCALL(name) \ - cond_syscall(sys_##name); \ + cond_syscall(__x64_sys_##name); \ cond_syscall(__ia32_sys_##name) #define SYS_NI(name) \ - SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers); \ + SYSCALL_ALIAS(__x64_sys_##name, sys_ni_posix_timers); \ SYSCALL_ALIAS(__ia32_sys_##name, sys_ni_posix_timers) #else /* CONFIG_IA32_EMULATION */ @@ -81,8 +92,7 @@ /* * Compat means IA32_EMULATION and/or X86_X32. As they use a different * mapping of registers to parameters, we need to generate stubs for each - * of them. There is no need to implement COMPAT_SYSCALL_DEFINE0, as it is - * unused on x86. + * of them. */ #define COMPAT_SYSCALL_DEFINEx(x, name, ...) \ static long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ @@ -114,13 +124,13 @@ /* * Instead of the generic __SYSCALL_DEFINEx() definition, this macro takes * struct pt_regs *regs as the only argument of the syscall stub named - * sys_*(). It decodes just the registers it needs and passes them on to + * __x64_sys_*(). It decodes just the registers it needs and passes them on to * the __se_sys_*() wrapper performing sign extension and then to the * __do_sys_*() function doing the actual job. These wrappers and functions * are inlined (at least in very most cases), meaning that the assembly looks * as follows (slightly re-ordered for better readability): * - * : <-- syscall with 4 parameters + * <__x64_sys_recv>: <-- syscall with 4 parameters * callq <__fentry__> * * mov 0x70(%rdi),%rdi <-- decode regs->di @@ -143,18 +153,13 @@ * If IA32_EMULATION is enabled, this macro generates an additional wrapper * named __ia32_sys_*() which decodes the struct pt_regs *regs according * to the i386 calling convention (bx, cx, dx, si, di, bp). - * - * As the generic SYSCALL_DEFINE0() macro does not decode any parameters for - * obvious reasons, and passing struct pt_regs *regs to it in %rdi does not - * hurt, there is no need to override it, or to define it differently for - * IA32_EMULATION. */ #define __SYSCALL_DEFINEx(x, name, ...) \ - asmlinkage long sys##name(const struct pt_regs *regs); \ - ALLOW_ERROR_INJECTION(sys##name, ERRNO); \ + asmlinkage long __x64_sys##name(const struct pt_regs *regs); \ + ALLOW_ERROR_INJECTION(__x64_sys##name, ERRNO); \ static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ - asmlinkage long sys##name(const struct pt_regs *regs) \ + asmlinkage long __x64_sys##name(const struct pt_regs *regs) \ { \ return __se_sys##name(SC_X86_64_REGS_TO_ARGS(x,__VA_ARGS__));\ } \ @@ -168,13 +173,37 @@ } \ static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) +/* + * As the generic SYSCALL_DEFINE0() macro does not decode any parameters for + * obvious reasons, and passing struct pt_regs *regs to it in %rdi does not + * hurt, we only need to re-define it here to keep the naming congruent to + * SYSCALL_DEFINEx() -- which is essential for the COND_SYSCALL() and SYS_NI() + * macros to work correctly. + */ +#ifndef SYSCALL_DEFINE0 +#define SYSCALL_DEFINE0(sname) \ + SYSCALL_METADATA(_##sname, 0); \ + asmlinkage long __x64_sys_##sname(void); \ + ALLOW_ERROR_INJECTION(__x64_sys_##sname, ERRNO); \ + asmlinkage long __x64_sys_##sname(void) +#endif + +#ifndef COND_SYSCALL +#define COND_SYSCALL(name) cond_syscall(__x64_sys_##name) +#endif + +#ifndef SYS_NI +#define SYS_NI(name) SYSCALL_ALIAS(__x64_sys_##name, sys_ni_posix_timers); +#endif + + /* * For VSYSCALLS, we need to declare these three syscalls with the new * pt_regs-based calling convention for in-kernel use. */ struct pt_regs; -asmlinkage long sys_getcpu(const struct pt_regs *regs); /* di,si,dx */ -asmlinkage long sys_gettimeofday(const struct pt_regs *regs); /* di,si */ -asmlinkage long sys_time(const struct pt_regs *regs); /* di */ +asmlinkage long __x64_sys_getcpu(const struct pt_regs *regs); +asmlinkage long __x64_sys_gettimeofday(const struct pt_regs *regs); +asmlinkage long __x64_sys_time(const struct pt_regs *regs); #endif /* _ASM_X86_SYSCALL_WRAPPER_H */ -- cgit v1.2.1 From c76fc98260751e71c884dc1a18a07e427ef033b5 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Mon, 9 Apr 2018 12:51:45 +0200 Subject: syscalls/x86: Adapt syscall_wrapper.h to the new syscall stub naming convention Make the code in syscall_wrapper.h more readable by naming the stub macros similar to the stub they provide. While at it, fix a stray newline at the end of the __IA32_COMPAT_SYS_STUBx macro. Signed-off-by: Dominik Brodowski Cc: Al Viro Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20180409105145.5364-5-linux@dominikbrodowski.net Signed-off-by: Ingo Molnar --- arch/x86/include/asm/syscall_wrapper.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'arch/x86/include/asm/syscall_wrapper.h') diff --git a/arch/x86/include/asm/syscall_wrapper.h b/arch/x86/include/asm/syscall_wrapper.h index a598013e08e9..e046a405743d 100644 --- a/arch/x86/include/asm/syscall_wrapper.h +++ b/arch/x86/include/asm/syscall_wrapper.h @@ -28,7 +28,7 @@ * kernel/sys_ni.c and SYS_NI in kernel/time/posix-stubs.c to cover this * case as well. */ -#define COMPAT_SC_IA32_STUBx(x, name, ...) \ +#define __IA32_COMPAT_SYS_STUBx(x, name, ...) \ asmlinkage long __ia32_compat_sys##name(const struct pt_regs *regs);\ ALLOW_ERROR_INJECTION(__ia32_compat_sys##name, ERRNO); \ asmlinkage long __ia32_compat_sys##name(const struct pt_regs *regs)\ @@ -36,7 +36,7 @@ return __se_compat_sys##name(SC_IA32_REGS_TO_ARGS(x,__VA_ARGS__));\ } \ -#define SC_IA32_WRAPPERx(x, name, ...) \ +#define __IA32_SYS_STUBx(x, name, ...) \ asmlinkage long __ia32_sys##name(const struct pt_regs *regs); \ ALLOW_ERROR_INJECTION(__ia32_sys##name, ERRNO); \ asmlinkage long __ia32_sys##name(const struct pt_regs *regs) \ @@ -64,8 +64,8 @@ SYSCALL_ALIAS(__ia32_sys_##name, sys_ni_posix_timers) #else /* CONFIG_IA32_EMULATION */ -#define COMPAT_SC_IA32_STUBx(x, name, ...) -#define SC_IA32_WRAPPERx(x, fullname, name, ...) +#define __IA32_COMPAT_SYS_STUBx(x, name, ...) +#define __IA32_SYS_STUBx(x, fullname, name, ...) #endif /* CONFIG_IA32_EMULATION */ @@ -75,7 +75,7 @@ * of the x86-64-style parameter ordering of x32 syscalls. The syscalls common * with x86_64 obviously do not need such care. */ -#define COMPAT_SC_X32_STUBx(x, name, ...) \ +#define __X32_COMPAT_SYS_STUBx(x, name, ...) \ asmlinkage long __x32_compat_sys##name(const struct pt_regs *regs);\ ALLOW_ERROR_INJECTION(__x32_compat_sys##name, ERRNO); \ asmlinkage long __x32_compat_sys##name(const struct pt_regs *regs)\ @@ -84,7 +84,7 @@ } \ #else /* CONFIG_X86_X32 */ -#define COMPAT_SC_X32_STUBx(x, name, ...) +#define __X32_COMPAT_SYS_STUBx(x, name, ...) #endif /* CONFIG_X86_X32 */ @@ -97,8 +97,8 @@ #define COMPAT_SYSCALL_DEFINEx(x, name, ...) \ static long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ - COMPAT_SC_IA32_STUBx(x, name, __VA_ARGS__) \ - COMPAT_SC_X32_STUBx(x, name, __VA_ARGS__) \ + __IA32_COMPAT_SYS_STUBx(x, name, __VA_ARGS__) \ + __X32_COMPAT_SYS_STUBx(x, name, __VA_ARGS__) \ static long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ { \ return __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__));\ @@ -163,7 +163,7 @@ { \ return __se_sys##name(SC_X86_64_REGS_TO_ARGS(x,__VA_ARGS__));\ } \ - SC_IA32_WRAPPERx(x, name, __VA_ARGS__) \ + __IA32_SYS_STUBx(x, name, __VA_ARGS__) \ static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ { \ long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\ -- cgit v1.2.1