1fa697140SDominik Brodowski /* SPDX-License-Identifier: GPL-2.0 */ 2fa697140SDominik Brodowski /* 3fa697140SDominik Brodowski * syscall_wrapper.h - x86 specific wrappers to syscall definitions 4fa697140SDominik Brodowski */ 5fa697140SDominik Brodowski 6fa697140SDominik Brodowski #ifndef _ASM_X86_SYSCALL_WRAPPER_H 7fa697140SDominik Brodowski #define _ASM_X86_SYSCALL_WRAPPER_H 8fa697140SDominik Brodowski 9fa697140SDominik Brodowski /* 10fa697140SDominik Brodowski * Instead of the generic __SYSCALL_DEFINEx() definition, this macro takes 11fa697140SDominik Brodowski * struct pt_regs *regs as the only argument of the syscall stub named 12fa697140SDominik Brodowski * sys_*(). It decodes just the registers it needs and passes them on to 13fa697140SDominik Brodowski * the SyS_*() wrapper and then to the SYSC_*() function doing the actual job. 14fa697140SDominik Brodowski * These wrappers and functions are inlined, meaning that the assembly looks 15fa697140SDominik Brodowski * as follows (slightly re-ordered): 16fa697140SDominik Brodowski * 17fa697140SDominik Brodowski * <sys_recv>: <-- syscall with 4 parameters 18fa697140SDominik Brodowski * callq <__fentry__> 19fa697140SDominik Brodowski * 20fa697140SDominik Brodowski * mov 0x70(%rdi),%rdi <-- decode regs->di 21fa697140SDominik Brodowski * mov 0x68(%rdi),%rsi <-- decode regs->si 22fa697140SDominik Brodowski * mov 0x60(%rdi),%rdx <-- decode regs->dx 23fa697140SDominik Brodowski * mov 0x38(%rdi),%rcx <-- decode regs->r10 24fa697140SDominik Brodowski * 25fa697140SDominik Brodowski * xor %r9d,%r9d <-- clear %r9 26fa697140SDominik Brodowski * xor %r8d,%r8d <-- clear %r8 27fa697140SDominik Brodowski * 28fa697140SDominik Brodowski * callq __sys_recvfrom <-- do the actual work in __sys_recvfrom() 29fa697140SDominik Brodowski * which takes 6 arguments 30fa697140SDominik Brodowski * 31fa697140SDominik Brodowski * cltq <-- extend return value to 64-bit 32fa697140SDominik Brodowski * retq <-- return 33fa697140SDominik Brodowski * 34fa697140SDominik Brodowski * This approach avoids leaking random user-provided register content down 35fa697140SDominik Brodowski * the call chain. 36fa697140SDominik Brodowski * 37fa697140SDominik Brodowski * As the generic SYSCALL_DEFINE0() macro does not decode any parameters for 38fa697140SDominik Brodowski * obvious reasons, and passing struct pt_regs *regs to it in %rdi does not 39fa697140SDominik Brodowski * hurt, there is no need to override it. 40fa697140SDominik Brodowski */ 41fa697140SDominik Brodowski #define __SYSCALL_DEFINEx(x, name, ...) \ 42fa697140SDominik Brodowski asmlinkage long sys##name(const struct pt_regs *regs); \ 43fa697140SDominik Brodowski ALLOW_ERROR_INJECTION(sys##name, ERRNO); \ 44fa697140SDominik Brodowski static long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ 45fa697140SDominik Brodowski static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ 46fa697140SDominik Brodowski asmlinkage long sys##name(const struct pt_regs *regs) \ 47fa697140SDominik Brodowski { \ 48fa697140SDominik Brodowski return SyS##name(__MAP(x,__SC_ARGS \ 49fa697140SDominik Brodowski ,,regs->di,,regs->si,,regs->dx \ 50fa697140SDominik Brodowski ,,regs->r10,,regs->r8,,regs->r9)); \ 51fa697140SDominik Brodowski } \ 52fa697140SDominik Brodowski static long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ 53fa697140SDominik Brodowski { \ 54fa697140SDominik Brodowski long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ 55fa697140SDominik Brodowski __MAP(x,__SC_TEST,__VA_ARGS__); \ 56fa697140SDominik Brodowski __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ 57fa697140SDominik Brodowski return ret; \ 58fa697140SDominik Brodowski } \ 59fa697140SDominik Brodowski static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)) 60fa697140SDominik Brodowski 61fa697140SDominik Brodowski /* 62fa697140SDominik Brodowski * For VSYSCALLS, we need to declare these three syscalls with the new 63fa697140SDominik Brodowski * pt_regs-based calling convention for in-kernel use. 64fa697140SDominik Brodowski */ 65fa697140SDominik Brodowski struct pt_regs; 66fa697140SDominik Brodowski asmlinkage long sys_getcpu(const struct pt_regs *regs); /* di,si,dx */ 67fa697140SDominik Brodowski asmlinkage long sys_gettimeofday(const struct pt_regs *regs); /* di,si */ 68fa697140SDominik Brodowski asmlinkage long sys_time(const struct pt_regs *regs); /* di */ 69fa697140SDominik Brodowski 70fa697140SDominik Brodowski #endif /* _ASM_X86_SYSCALL_WRAPPER_H */ 71