diff options
author | Mickaël Salaün <mic@digikod.net> | 2015-12-29 23:35:46 +0300 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2016-01-10 23:49:49 +0300 |
commit | d8f8b8445648c267a24f30a72533e77cb6543f21 (patch) | |
tree | 771077fdccf7ec1b8b1f09324210867796a52dcd /arch | |
parent | 4a0b88070406323487bad730d8945f482151a145 (diff) | |
download | linux-d8f8b8445648c267a24f30a72533e77cb6543f21.tar.xz |
um: Add full asm/syscall.h support
Add subarchitecture-independent implementation of asm-generic/syscall.h
allowing access to user system call parameters and results:
* syscall_get_nr()
* syscall_rollback()
* syscall_get_error()
* syscall_get_return_value()
* syscall_set_return_value()
* syscall_get_arguments()
* syscall_set_arguments()
* syscall_get_arch() provided by arch/x86/um/asm/syscall.h
This provides the necessary syscall helpers needed by
HAVE_ARCH_SECCOMP_FILTER plus syscall_get_error().
This is inspired from Meredydd Luff's patch
(https://gerrit.chromium.org/gerrit/21425).
Signed-off-by: Mickaël Salaün <mic@digikod.net>
Cc: Jeff Dike <jdike@addtoit.com>
Cc: Richard Weinberger <richard@nod.at>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Will Drewry <wad@chromium.org>
Cc: Meredydd Luff <meredydd@senatehouse.org>
Cc: David Drysdale <drysdale@google.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
Acked-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/um/include/asm/syscall-generic.h | 138 | ||||
-rw-r--r-- | arch/x86/um/asm/syscall.h | 1 |
2 files changed, 139 insertions, 0 deletions
diff --git a/arch/um/include/asm/syscall-generic.h b/arch/um/include/asm/syscall-generic.h new file mode 100644 index 000000000000..9fb9cf8cd39a --- /dev/null +++ b/arch/um/include/asm/syscall-generic.h @@ -0,0 +1,138 @@ +/* + * Access to user system call parameters and results + * + * See asm-generic/syscall.h for function descriptions. + * + * Copyright (C) 2015 Mickaël Salaün <mic@digikod.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __UM_SYSCALL_GENERIC_H +#define __UM_SYSCALL_GENERIC_H + +#include <asm/ptrace.h> +#include <linux/err.h> +#include <linux/sched.h> +#include <sysdep/ptrace.h> + +static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) +{ + + return PT_REGS_SYSCALL_NR(regs); +} + +static inline void syscall_rollback(struct task_struct *task, + struct pt_regs *regs) +{ + /* do nothing */ +} + +static inline long syscall_get_error(struct task_struct *task, + struct pt_regs *regs) +{ + const long error = regs_return_value(regs); + + return IS_ERR_VALUE(error) ? error : 0; +} + +static inline long syscall_get_return_value(struct task_struct *task, + struct pt_regs *regs) +{ + return regs_return_value(regs); +} + +static inline void syscall_set_return_value(struct task_struct *task, + struct pt_regs *regs, + int error, long val) +{ + PT_REGS_SET_SYSCALL_RETURN(regs, (long) error ?: val); +} + +static inline void syscall_get_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + unsigned long *args) +{ + const struct uml_pt_regs *r = ®s->regs; + + switch (i) { + case 0: + if (!n--) + break; + *args++ = UPT_SYSCALL_ARG1(r); + case 1: + if (!n--) + break; + *args++ = UPT_SYSCALL_ARG2(r); + case 2: + if (!n--) + break; + *args++ = UPT_SYSCALL_ARG3(r); + case 3: + if (!n--) + break; + *args++ = UPT_SYSCALL_ARG4(r); + case 4: + if (!n--) + break; + *args++ = UPT_SYSCALL_ARG5(r); + case 5: + if (!n--) + break; + *args++ = UPT_SYSCALL_ARG6(r); + case 6: + if (!n--) + break; + default: + BUG(); + break; + } +} + +static inline void syscall_set_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + const unsigned long *args) +{ + struct uml_pt_regs *r = ®s->regs; + + switch (i) { + case 0: + if (!n--) + break; + UPT_SYSCALL_ARG1(r) = *args++; + case 1: + if (!n--) + break; + UPT_SYSCALL_ARG2(r) = *args++; + case 2: + if (!n--) + break; + UPT_SYSCALL_ARG3(r) = *args++; + case 3: + if (!n--) + break; + UPT_SYSCALL_ARG4(r) = *args++; + case 4: + if (!n--) + break; + UPT_SYSCALL_ARG5(r) = *args++; + case 5: + if (!n--) + break; + UPT_SYSCALL_ARG6(r) = *args++; + case 6: + if (!n--) + break; + default: + BUG(); + break; + } +} + +/* See arch/x86/um/asm/syscall.h for syscall_get_arch() definition. */ + +#endif /* __UM_SYSCALL_GENERIC_H */ diff --git a/arch/x86/um/asm/syscall.h b/arch/x86/um/asm/syscall.h index 81d6562ce01d..11ab90dc5f14 100644 --- a/arch/x86/um/asm/syscall.h +++ b/arch/x86/um/asm/syscall.h @@ -1,6 +1,7 @@ #ifndef __UM_ASM_SYSCALL_H #define __UM_ASM_SYSCALL_H +#include <asm/syscall-generic.h> #include <uapi/linux/audit.h> typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long, |