diff options
author | Mickaël Salaün <mic@digikod.net> | 2015-12-29 15:35:46 -0500 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2016-01-10 15:49:49 -0500 |
commit | d8f8b8445648c267a24f30a72533e77cb6543f21 (patch) | |
tree | 771077fdccf7ec1b8b1f09324210867796a52dcd | |
parent | 4a0b88070406323487bad730d8945f482151a145 (diff) |
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>
-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 @@ | |||
1 | /* | ||
2 | * Access to user system call parameters and results | ||
3 | * | ||
4 | * See asm-generic/syscall.h for function descriptions. | ||
5 | * | ||
6 | * Copyright (C) 2015 Mickaël Salaün <mic@digikod.net> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __UM_SYSCALL_GENERIC_H | ||
14 | #define __UM_SYSCALL_GENERIC_H | ||
15 | |||
16 | #include <asm/ptrace.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <sysdep/ptrace.h> | ||
20 | |||
21 | static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) | ||
22 | { | ||
23 | |||
24 | return PT_REGS_SYSCALL_NR(regs); | ||
25 | } | ||
26 | |||
27 | static inline void syscall_rollback(struct task_struct *task, | ||
28 | struct pt_regs *regs) | ||
29 | { | ||
30 | /* do nothing */ | ||
31 | } | ||
32 | |||
33 | static inline long syscall_get_error(struct task_struct *task, | ||
34 | struct pt_regs *regs) | ||
35 | { | ||
36 | const long error = regs_return_value(regs); | ||
37 | |||
38 | return IS_ERR_VALUE(error) ? error : 0; | ||
39 | } | ||
40 | |||
41 | static inline long syscall_get_return_value(struct task_struct *task, | ||
42 | struct pt_regs *regs) | ||
43 | { | ||
44 | return regs_return_value(regs); | ||
45 | } | ||
46 | |||
47 | static inline void syscall_set_return_value(struct task_struct *task, | ||
48 | struct pt_regs *regs, | ||
49 | int error, long val) | ||
50 | { | ||
51 | PT_REGS_SET_SYSCALL_RETURN(regs, (long) error ?: val); | ||
52 | } | ||
53 | |||
54 | static inline void syscall_get_arguments(struct task_struct *task, | ||
55 | struct pt_regs *regs, | ||
56 | unsigned int i, unsigned int n, | ||
57 | unsigned long *args) | ||
58 | { | ||
59 | const struct uml_pt_regs *r = ®s->regs; | ||
60 | |||
61 | switch (i) { | ||
62 | case 0: | ||
63 | if (!n--) | ||
64 | break; | ||
65 | *args++ = UPT_SYSCALL_ARG1(r); | ||
66 | case 1: | ||
67 | if (!n--) | ||
68 | break; | ||
69 | *args++ = UPT_SYSCALL_ARG2(r); | ||
70 | case 2: | ||
71 | if (!n--) | ||
72 | break; | ||
73 | *args++ = UPT_SYSCALL_ARG3(r); | ||
74 | case 3: | ||
75 | if (!n--) | ||
76 | break; | ||
77 | *args++ = UPT_SYSCALL_ARG4(r); | ||
78 | case 4: | ||
79 | if (!n--) | ||
80 | break; | ||
81 | *args++ = UPT_SYSCALL_ARG5(r); | ||
82 | case 5: | ||
83 | if (!n--) | ||
84 | break; | ||
85 | *args++ = UPT_SYSCALL_ARG6(r); | ||
86 | case 6: | ||
87 | if (!n--) | ||
88 | break; | ||
89 | default: | ||
90 | BUG(); | ||
91 | break; | ||
92 | } | ||
93 | } | ||
94 | |||
95 | static inline void syscall_set_arguments(struct task_struct *task, | ||
96 | struct pt_regs *regs, | ||
97 | unsigned int i, unsigned int n, | ||
98 | const unsigned long *args) | ||
99 | { | ||
100 | struct uml_pt_regs *r = ®s->regs; | ||
101 | |||
102 | switch (i) { | ||
103 | case 0: | ||
104 | if (!n--) | ||
105 | break; | ||
106 | UPT_SYSCALL_ARG1(r) = *args++; | ||
107 | case 1: | ||
108 | if (!n--) | ||
109 | break; | ||
110 | UPT_SYSCALL_ARG2(r) = *args++; | ||
111 | case 2: | ||
112 | if (!n--) | ||
113 | break; | ||
114 | UPT_SYSCALL_ARG3(r) = *args++; | ||
115 | case 3: | ||
116 | if (!n--) | ||
117 | break; | ||
118 | UPT_SYSCALL_ARG4(r) = *args++; | ||
119 | case 4: | ||
120 | if (!n--) | ||
121 | break; | ||
122 | UPT_SYSCALL_ARG5(r) = *args++; | ||
123 | case 5: | ||
124 | if (!n--) | ||
125 | break; | ||
126 | UPT_SYSCALL_ARG6(r) = *args++; | ||
127 | case 6: | ||
128 | if (!n--) | ||
129 | break; | ||
130 | default: | ||
131 | BUG(); | ||
132 | break; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | /* See arch/x86/um/asm/syscall.h for syscall_get_arch() definition. */ | ||
137 | |||
138 | #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 @@ | |||
1 | #ifndef __UM_ASM_SYSCALL_H | 1 | #ifndef __UM_ASM_SYSCALL_H |
2 | #define __UM_ASM_SYSCALL_H | 2 | #define __UM_ASM_SYSCALL_H |
3 | 3 | ||
4 | #include <asm/syscall-generic.h> | ||
4 | #include <uapi/linux/audit.h> | 5 | #include <uapi/linux/audit.h> |
5 | 6 | ||
6 | typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long, | 7 | typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long, |