s390: autogenerate compat syscall wrappers
Any system call that takes a pointer argument on s390 requires
a wrapper function to do a 31-to-64 zero-extension, these are
currently generated in arch/s390/kernel/compat_wrapper.c.
On arm64 and x86, we already generate similar wrappers for all
system calls in the place of their definition, just for a different
purpose (they load the arguments from pt_regs).
We can do the same thing here, by adding an asm/syscall_wrapper.h
file with a copy of all the relevant macros to override the generic
version. Besides the addition of the compat entry point, these also
rename the entry points with a __s390_ or __s390x_ prefix, similar
to what we do on arm64 and x86. This in turn requires renaming
a few things, and adding a proper ni_syscall() entry point.
In order to still compile system call definitions that pass an
loff_t argument, the __SC_COMPAT_CAST() macro checks for that
and forces an -ENOSYS error, which was the best I could come up
with. Those functions must obviously not get called from user
space, but instead require hand-written compat_sys_*() handlers,
which fortunately already exist.
Link: https://lore.kernel.org/lkml/20190116131527.2071570-5-arnd@arndb.de
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
[heiko.carstens@de.ibm.com: compile fix for !CONFIG_COMPAT]
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
2019-01-16 14:15:22 +01:00
/* SPDX-License-Identifier: GPL-2.0 */
/*
* syscall_wrapper . h - s390 specific wrappers to syscall definitions
*
*/
# ifndef _ASM_S390_SYSCALL_WRAPPER_H
# define _ASM_S390_SYSCALL_WRAPPER_H
# ifdef CONFIG_COMPAT
# define __SC_COMPAT_TYPE(t, a) \
__typeof ( __builtin_choose_expr ( sizeof ( t ) > 4 , 0L , ( t ) 0 ) ) a
# define __SC_COMPAT_CAST(t, a) \
( { \
long __ReS = a ; \
\
BUILD_BUG_ON ( ( sizeof ( t ) > 4 ) & & ! __TYPE_IS_L ( t ) & & \
! __TYPE_IS_UL ( t ) & & ! __TYPE_IS_PTR ( t ) & & \
! __TYPE_IS_LL ( t ) ) ; \
if ( __TYPE_IS_L ( t ) ) \
__ReS = ( s32 ) a ; \
if ( __TYPE_IS_UL ( t ) ) \
__ReS = ( u32 ) a ; \
if ( __TYPE_IS_PTR ( t ) ) \
__ReS = a & 0x7fffffff ; \
if ( __TYPE_IS_LL ( t ) ) \
return - ENOSYS ; \
( t ) __ReS ; \
} )
# define __S390_SYS_STUBx(x, name, ...) \
asmlinkage long __s390_sys # # name ( __MAP ( x , __SC_LONG , __VA_ARGS__ ) ) \
ALLOW_ERROR_INJECTION ( __s390_sys # # name , ERRNO ) ; \
asmlinkage long __s390_sys # # name ( __MAP ( x , __SC_LONG , __VA_ARGS__ ) ) \
{ \
long ret = __s390x_sys # # name ( __MAP ( x , __SC_COMPAT_CAST , __VA_ARGS__ ) ) ; \
__MAP ( x , __SC_TEST , __VA_ARGS__ ) ; \
return ret ; \
}
/*
* To keep the naming coherent , re - define SYSCALL_DEFINE0 to create an alias
* named __s390x_sys_ * ( )
*/
# define COMPAT_SYSCALL_DEFINE0(sname) \
SYSCALL_METADATA ( _ # # sname , 0 ) ; \
asmlinkage long __s390_compat_sys_ # # sname ( void ) ; \
ALLOW_ERROR_INJECTION ( __s390_compat__sys_ # # sname , ERRNO ) ; \
asmlinkage long __s390_compat_sys_ # # sname ( void )
# define SYSCALL_DEFINE0(sname) \
SYSCALL_METADATA ( _ # # sname , 0 ) ; \
asmlinkage long __s390x_sys_ # # sname ( void ) ; \
ALLOW_ERROR_INJECTION ( __s390x_sys_ # # sname , ERRNO ) ; \
asmlinkage long __s390_sys_ # # sname ( void ) \
__attribute__ ( ( alias ( __stringify ( __s390x_sys_ # # sname ) ) ) ) ; \
asmlinkage long __s390x_sys_ # # sname ( void )
# define COND_SYSCALL(name) \
cond_syscall ( __s390x_sys_ # # name ) ; \
cond_syscall ( __s390_sys_ # # name )
# define SYS_NI(name) \
SYSCALL_ALIAS ( __s390x_sys_ # # name , sys_ni_posix_timers ) ; \
SYSCALL_ALIAS ( __s390_sys_ # # name , sys_ni_posix_timers )
# define COMPAT_SYSCALL_DEFINEx(x, name, ...) \
__diag_push ( ) ; \
__diag_ignore ( GCC , 8 , " -Wattribute-alias " , \
" Type aliasing is used to sanitize syscall arguments " ) ; \
asmlinkage long __s390_compat_sys # # name ( __MAP ( x , __SC_DECL , __VA_ARGS__ ) ) ; \
asmlinkage long __s390_compat_sys # # name ( __MAP ( x , __SC_DECL , __VA_ARGS__ ) ) \
__attribute__ ( ( alias ( __stringify ( __se_compat_sys # # name ) ) ) ) ; \
ALLOW_ERROR_INJECTION ( compat_sys # # name , ERRNO ) ; \
static inline long __do_compat_sys # # name ( __MAP ( x , __SC_DECL , __VA_ARGS__ ) ) ; \
asmlinkage long __se_compat_sys # # name ( __MAP ( x , __SC_LONG , __VA_ARGS__ ) ) ; \
asmlinkage long __se_compat_sys # # name ( __MAP ( x , __SC_LONG , __VA_ARGS__ ) ) \
{ \
long ret = __do_compat_sys # # name ( __MAP ( x , __SC_DELOUSE , __VA_ARGS__ ) ) ; \
__MAP ( x , __SC_TEST , __VA_ARGS__ ) ; \
return ret ; \
} \
__diag_pop ( ) ; \
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
* 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 ( __s390_compat_sys_ # # name )
# define COMPAT_SYS_NI(name) \
SYSCALL_ALIAS ( __s390_compat_sys_ # # name , sys_ni_posix_timers )
# else /* CONFIG_COMPAT */
# define __S390_SYS_STUBx(x, fullname, name, ...)
# define SYSCALL_DEFINE0(sname) \
SYSCALL_METADATA ( _ # # sname , 0 ) ; \
asmlinkage long __s390x_sys_ # # sname ( void ) ; \
ALLOW_ERROR_INJECTION ( __s390x_sys_ # # sname , ERRNO ) ; \
asmlinkage long __s390x_sys_ # # sname ( void )
# define COND_SYSCALL(name) \
cond_syscall ( __s390x_sys_ # # name )
# define SYS_NI(name) \
SYSCALL_ALIAS ( __s390x_sys_ # # name , sys_ni_posix_timers ) ;
# endif /* CONFIG_COMPAT */
# define __SYSCALL_DEFINEx(x, name, ...) \
__diag_push ( ) ; \
__diag_ignore ( GCC , 8 , " -Wattribute-alias " , \
" Type aliasing is used to sanitize syscall arguments " ) ; \
asmlinkage long __s390x_sys # # name ( __MAP ( x , __SC_DECL , __VA_ARGS__ ) ) \
__attribute__ ( ( alias ( __stringify ( __se_sys # # name ) ) ) ) ; \
s390: syscall_wrapper: avoid clang warning
Building system calls with clang results in a warning
about an alias from a global function to a static one:
../fs/namei.c:3847:1: warning: unused function '__se_sys_mkdirat' [-Wunused-function]
SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
^
../include/linux/syscalls.h:219:36: note: expanded from macro 'SYSCALL_DEFINE3'
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
^
../include/linux/syscalls.h:228:2: note: expanded from macro 'SYSCALL_DEFINEx'
__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
^
../arch/s390/include/asm/syscall_wrapper.h:126:18: note: expanded from macro '__SYSCALL_DEFINEx'
asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
^
<scratch space>:31:1: note: expanded from here
__se_sys_mkdirat
^
The only reference to the static __se_sys_mkdirat() here is the alias, but
this only gets evaluated later. Making this function global as well avoids
the warning.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
2019-04-08 23:26:21 +02:00
ALLOW_ERROR_INJECTION ( __s390x_sys # # name , ERRNO ) ; \
long __se_sys # # name ( __MAP ( x , __SC_LONG , __VA_ARGS__ ) ) ; \
s390: autogenerate compat syscall wrappers
Any system call that takes a pointer argument on s390 requires
a wrapper function to do a 31-to-64 zero-extension, these are
currently generated in arch/s390/kernel/compat_wrapper.c.
On arm64 and x86, we already generate similar wrappers for all
system calls in the place of their definition, just for a different
purpose (they load the arguments from pt_regs).
We can do the same thing here, by adding an asm/syscall_wrapper.h
file with a copy of all the relevant macros to override the generic
version. Besides the addition of the compat entry point, these also
rename the entry points with a __s390_ or __s390x_ prefix, similar
to what we do on arm64 and x86. This in turn requires renaming
a few things, and adding a proper ni_syscall() entry point.
In order to still compile system call definitions that pass an
loff_t argument, the __SC_COMPAT_CAST() macro checks for that
and forces an -ENOSYS error, which was the best I could come up
with. Those functions must obviously not get called from user
space, but instead require hand-written compat_sys_*() handlers,
which fortunately already exist.
Link: https://lore.kernel.org/lkml/20190116131527.2071570-5-arnd@arndb.de
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
[heiko.carstens@de.ibm.com: compile fix for !CONFIG_COMPAT]
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
2019-01-16 14:15:22 +01:00
static inline long __do_sys # # name ( __MAP ( x , __SC_DECL , __VA_ARGS__ ) ) ; \
__S390_SYS_STUBx ( x , name , __VA_ARGS__ ) \
asmlinkage long __se_sys # # name ( __MAP ( x , __SC_LONG , __VA_ARGS__ ) ) \
{ \
long ret = __do_sys # # name ( __MAP ( x , __SC_CAST , __VA_ARGS__ ) ) ; \
__MAP ( x , __SC_TEST , __VA_ARGS__ ) ; \
return ret ; \
} \
__diag_pop ( ) ; \
static inline long __do_sys # # name ( __MAP ( x , __SC_DECL , __VA_ARGS__ ) )
# endif /* _ASM_X86_SYSCALL_WRAPPER_H */