1bb898558SAl Viro /* 2bb898558SAl Viro * Access to user system call parameters and results 3bb898558SAl Viro * 418c1e2c8SRoland McGrath * Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved. 5bb898558SAl Viro * 6bb898558SAl Viro * This copyrighted material is made available to anyone wishing to use, 7bb898558SAl Viro * modify, copy, or redistribute it subject to the terms and conditions 8bb898558SAl Viro * of the GNU General Public License v.2. 9bb898558SAl Viro * 10bb898558SAl Viro * See asm-generic/syscall.h for descriptions of what we must do here. 11bb898558SAl Viro */ 12bb898558SAl Viro 135e1b0075SH. Peter Anvin #ifndef _ASM_X86_SYSCALL_H 145e1b0075SH. Peter Anvin #define _ASM_X86_SYSCALL_H 15bb898558SAl Viro 16579ec9e1SEric Paris #include <uapi/linux/audit.h> 17bb898558SAl Viro #include <linux/sched.h> 18bb898558SAl Viro #include <linux/err.h> 1972142fd4SH. Peter Anvin #include <asm/asm-offsets.h> /* For NR_syscalls */ 20b7456536SWill Drewry #include <asm/thread_info.h> /* for TS_COMPAT */ 21fca460f9SH. Peter Anvin #include <asm/unistd.h> 22bb898558SAl Viro 23eb974c62SAndy Lutomirski typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long, 24eb974c62SAndy Lutomirski unsigned long, unsigned long, 25eb974c62SAndy Lutomirski unsigned long, unsigned long); 261599e8fcSAndi Kleen extern const sys_call_ptr_t sys_call_table[]; 27e7b8e675SMike Frysinger 28034042ccSAndy Lutomirski #if defined(CONFIG_X86_32) 29034042ccSAndy Lutomirski #define ia32_sys_call_table sys_call_table 30034042ccSAndy Lutomirski #define __NR_syscall_compat_max __NR_syscall_max 31034042ccSAndy Lutomirski #define IA32_NR_syscalls NR_syscalls 32034042ccSAndy Lutomirski #endif 33034042ccSAndy Lutomirski 34034042ccSAndy Lutomirski #if defined(CONFIG_IA32_EMULATION) 35034042ccSAndy Lutomirski extern const sys_call_ptr_t ia32_sys_call_table[]; 36034042ccSAndy Lutomirski #endif 37034042ccSAndy Lutomirski 38bb898558SAl Viro /* 3918c1e2c8SRoland McGrath * Only the low 32 bits of orig_ax are meaningful, so we return int. 4018c1e2c8SRoland McGrath * This importantly ignores the high bits on 64-bit, so comparisons 4118c1e2c8SRoland McGrath * sign-extend the low 32 bits. 42bb898558SAl Viro */ 4318c1e2c8SRoland McGrath static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) 4418c1e2c8SRoland McGrath { 458b4b9f27SPaul Moore return regs->orig_ax; 46bb898558SAl Viro } 47bb898558SAl Viro 48bb898558SAl Viro static inline void syscall_rollback(struct task_struct *task, 49bb898558SAl Viro struct pt_regs *regs) 50bb898558SAl Viro { 518b4b9f27SPaul Moore regs->ax = regs->orig_ax; 52bb898558SAl Viro } 53bb898558SAl Viro 54bb898558SAl Viro static inline long syscall_get_error(struct task_struct *task, 55bb898558SAl Viro struct pt_regs *regs) 56bb898558SAl Viro { 57bb898558SAl Viro unsigned long error = regs->ax; 58bb898558SAl Viro #ifdef CONFIG_IA32_EMULATION 59bb898558SAl Viro /* 60bb898558SAl Viro * TS_COMPAT is set for 32-bit syscall entries and then 61bb898558SAl Viro * remains set until we return to user mode. 62bb898558SAl Viro */ 63*37a8f7c3SAndy Lutomirski if (task->thread_info.status & (TS_COMPAT|TS_I386_REGS_POKED)) 64bb898558SAl Viro /* 65bb898558SAl Viro * Sign-extend the value so (int)-EFOO becomes (long)-EFOO 66bb898558SAl Viro * and will match correctly in comparisons. 67bb898558SAl Viro */ 68bb898558SAl Viro error = (long) (int) error; 69bb898558SAl Viro #endif 70bb898558SAl Viro return IS_ERR_VALUE(error) ? error : 0; 71bb898558SAl Viro } 72bb898558SAl Viro 73bb898558SAl Viro static inline long syscall_get_return_value(struct task_struct *task, 74bb898558SAl Viro struct pt_regs *regs) 75bb898558SAl Viro { 76bb898558SAl Viro return regs->ax; 77bb898558SAl Viro } 78bb898558SAl Viro 79bb898558SAl Viro static inline void syscall_set_return_value(struct task_struct *task, 80bb898558SAl Viro struct pt_regs *regs, 81bb898558SAl Viro int error, long val) 82bb898558SAl Viro { 83bb898558SAl Viro regs->ax = (long) error ?: val; 84bb898558SAl Viro } 85bb898558SAl Viro 86bb898558SAl Viro #ifdef CONFIG_X86_32 87bb898558SAl Viro 88bb898558SAl Viro static inline void syscall_get_arguments(struct task_struct *task, 89bb898558SAl Viro struct pt_regs *regs, 90bb898558SAl Viro unsigned int i, unsigned int n, 91bb898558SAl Viro unsigned long *args) 92bb898558SAl Viro { 93bb898558SAl Viro BUG_ON(i + n > 6); 94bb898558SAl Viro memcpy(args, ®s->bx + i, n * sizeof(args[0])); 95bb898558SAl Viro } 96bb898558SAl Viro 97bb898558SAl Viro static inline void syscall_set_arguments(struct task_struct *task, 98bb898558SAl Viro struct pt_regs *regs, 99bb898558SAl Viro unsigned int i, unsigned int n, 100bb898558SAl Viro const unsigned long *args) 101bb898558SAl Viro { 102bb898558SAl Viro BUG_ON(i + n > 6); 103bb898558SAl Viro memcpy(®s->bx + i, args, n * sizeof(args[0])); 104bb898558SAl Viro } 105bb898558SAl Viro 1065e937a9aSEric Paris static inline int syscall_get_arch(void) 107b7456536SWill Drewry { 108b7456536SWill Drewry return AUDIT_ARCH_I386; 109b7456536SWill Drewry } 110b7456536SWill Drewry 111bb898558SAl Viro #else /* CONFIG_X86_64 */ 112bb898558SAl Viro 113bb898558SAl Viro static inline void syscall_get_arguments(struct task_struct *task, 114bb898558SAl Viro struct pt_regs *regs, 115bb898558SAl Viro unsigned int i, unsigned int n, 116bb898558SAl Viro unsigned long *args) 117bb898558SAl Viro { 118bb898558SAl Viro # ifdef CONFIG_IA32_EMULATION 119*37a8f7c3SAndy Lutomirski if (task->thread_info.status & TS_COMPAT) 120c3c9897cSLinus Torvalds switch (i) { 121c3c9897cSLinus Torvalds case 0: 122bb898558SAl Viro if (!n--) break; 123bb898558SAl Viro *args++ = regs->bx; 124c3c9897cSLinus Torvalds case 1: 125c3c9897cSLinus Torvalds if (!n--) break; 126c3c9897cSLinus Torvalds *args++ = regs->cx; 127c3c9897cSLinus Torvalds case 2: 128c3c9897cSLinus Torvalds if (!n--) break; 129c3c9897cSLinus Torvalds *args++ = regs->dx; 130c3c9897cSLinus Torvalds case 3: 131c3c9897cSLinus Torvalds if (!n--) break; 132c3c9897cSLinus Torvalds *args++ = regs->si; 133c3c9897cSLinus Torvalds case 4: 134c3c9897cSLinus Torvalds if (!n--) break; 135c3c9897cSLinus Torvalds *args++ = regs->di; 136c3c9897cSLinus Torvalds case 5: 137c3c9897cSLinus Torvalds if (!n--) break; 138c3c9897cSLinus Torvalds *args++ = regs->bp; 139c3c9897cSLinus Torvalds case 6: 140bb898558SAl Viro if (!n--) break; 141bb898558SAl Viro default: 142bb898558SAl Viro BUG(); 143bb898558SAl Viro break; 144bb898558SAl Viro } 145bb898558SAl Viro else 146bb898558SAl Viro # endif 147c3c9897cSLinus Torvalds switch (i) { 148c3c9897cSLinus Torvalds case 0: 149bb898558SAl Viro if (!n--) break; 150bb898558SAl Viro *args++ = regs->di; 151c3c9897cSLinus Torvalds case 1: 152c3c9897cSLinus Torvalds if (!n--) break; 153c3c9897cSLinus Torvalds *args++ = regs->si; 154c3c9897cSLinus Torvalds case 2: 155c3c9897cSLinus Torvalds if (!n--) break; 156c3c9897cSLinus Torvalds *args++ = regs->dx; 157c3c9897cSLinus Torvalds case 3: 158c3c9897cSLinus Torvalds if (!n--) break; 159c3c9897cSLinus Torvalds *args++ = regs->r10; 160c3c9897cSLinus Torvalds case 4: 161c3c9897cSLinus Torvalds if (!n--) break; 162c3c9897cSLinus Torvalds *args++ = regs->r8; 163c3c9897cSLinus Torvalds case 5: 164c3c9897cSLinus Torvalds if (!n--) break; 165c3c9897cSLinus Torvalds *args++ = regs->r9; 166c3c9897cSLinus Torvalds case 6: 167bb898558SAl Viro if (!n--) break; 168bb898558SAl Viro default: 169bb898558SAl Viro BUG(); 170bb898558SAl Viro break; 171bb898558SAl Viro } 172bb898558SAl Viro } 173bb898558SAl Viro 174bb898558SAl Viro static inline void syscall_set_arguments(struct task_struct *task, 175bb898558SAl Viro struct pt_regs *regs, 176bb898558SAl Viro unsigned int i, unsigned int n, 177bb898558SAl Viro const unsigned long *args) 178bb898558SAl Viro { 179bb898558SAl Viro # ifdef CONFIG_IA32_EMULATION 180*37a8f7c3SAndy Lutomirski if (task->thread_info.status & TS_COMPAT) 181c3c9897cSLinus Torvalds switch (i) { 182c3c9897cSLinus Torvalds case 0: 183bb898558SAl Viro if (!n--) break; 184bb898558SAl Viro regs->bx = *args++; 185c3c9897cSLinus Torvalds case 1: 186c3c9897cSLinus Torvalds if (!n--) break; 187c3c9897cSLinus Torvalds regs->cx = *args++; 188c3c9897cSLinus Torvalds case 2: 189c3c9897cSLinus Torvalds if (!n--) break; 190c3c9897cSLinus Torvalds regs->dx = *args++; 191c3c9897cSLinus Torvalds case 3: 192c3c9897cSLinus Torvalds if (!n--) break; 193c3c9897cSLinus Torvalds regs->si = *args++; 194c3c9897cSLinus Torvalds case 4: 195c3c9897cSLinus Torvalds if (!n--) break; 196c3c9897cSLinus Torvalds regs->di = *args++; 197c3c9897cSLinus Torvalds case 5: 198c3c9897cSLinus Torvalds if (!n--) break; 199c3c9897cSLinus Torvalds regs->bp = *args++; 200c3c9897cSLinus Torvalds case 6: 201bb898558SAl Viro if (!n--) break; 202bb898558SAl Viro default: 203bb898558SAl Viro BUG(); 204c3c9897cSLinus Torvalds break; 205bb898558SAl Viro } 206bb898558SAl Viro else 207bb898558SAl Viro # endif 208c3c9897cSLinus Torvalds switch (i) { 209c3c9897cSLinus Torvalds case 0: 210bb898558SAl Viro if (!n--) break; 211bb898558SAl Viro regs->di = *args++; 212c3c9897cSLinus Torvalds case 1: 213c3c9897cSLinus Torvalds if (!n--) break; 214c3c9897cSLinus Torvalds regs->si = *args++; 215c3c9897cSLinus Torvalds case 2: 216c3c9897cSLinus Torvalds if (!n--) break; 217c3c9897cSLinus Torvalds regs->dx = *args++; 218c3c9897cSLinus Torvalds case 3: 219c3c9897cSLinus Torvalds if (!n--) break; 220c3c9897cSLinus Torvalds regs->r10 = *args++; 221c3c9897cSLinus Torvalds case 4: 222c3c9897cSLinus Torvalds if (!n--) break; 223c3c9897cSLinus Torvalds regs->r8 = *args++; 224c3c9897cSLinus Torvalds case 5: 225c3c9897cSLinus Torvalds if (!n--) break; 226c3c9897cSLinus Torvalds regs->r9 = *args++; 227c3c9897cSLinus Torvalds case 6: 228bb898558SAl Viro if (!n--) break; 229bb898558SAl Viro default: 230bb898558SAl Viro BUG(); 231c3c9897cSLinus Torvalds break; 232bb898558SAl Viro } 233bb898558SAl Viro } 234bb898558SAl Viro 2355e937a9aSEric Paris static inline int syscall_get_arch(void) 236b7456536SWill Drewry { 237b9d989c7SAndy Lutomirski /* x32 tasks should be considered AUDIT_ARCH_X86_64. */ 238b9d989c7SAndy Lutomirski return in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; 239b7456536SWill Drewry } 240bb898558SAl Viro #endif /* CONFIG_X86_32 */ 241bb898558SAl Viro 2425e1b0075SH. Peter Anvin #endif /* _ASM_X86_SYSCALL_H */ 243