| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Access to user system call parameters and results |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved. |
|---|
| 5 | | - * |
|---|
| 6 | | - * This copyrighted material is made available to anyone wishing to use, |
|---|
| 7 | | - * modify, copy, or redistribute it subject to the terms and conditions |
|---|
| 8 | | - * of the GNU General Public License v.2. |
|---|
| 9 | 6 | * |
|---|
| 10 | 7 | * See asm-generic/syscall.h for descriptions of what we must do here. |
|---|
| 11 | 8 | */ |
|---|
| .. | .. |
|---|
| 16 | 13 | #include <uapi/linux/audit.h> |
|---|
| 17 | 14 | #include <linux/sched.h> |
|---|
| 18 | 15 | #include <linux/err.h> |
|---|
| 19 | | -#include <asm/asm-offsets.h> /* For NR_syscalls */ |
|---|
| 20 | 16 | #include <asm/thread_info.h> /* for TS_COMPAT */ |
|---|
| 21 | 17 | #include <asm/unistd.h> |
|---|
| 22 | 18 | |
|---|
| 23 | | -#ifdef CONFIG_X86_64 |
|---|
| 24 | | -typedef asmlinkage long (*sys_call_ptr_t)(const struct pt_regs *); |
|---|
| 25 | | -#else |
|---|
| 26 | | -typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long, |
|---|
| 27 | | - unsigned long, unsigned long, |
|---|
| 28 | | - unsigned long, unsigned long); |
|---|
| 29 | | -#endif /* CONFIG_X86_64 */ |
|---|
| 19 | +typedef long (*sys_call_ptr_t)(const struct pt_regs *); |
|---|
| 30 | 20 | extern const sys_call_ptr_t sys_call_table[]; |
|---|
| 31 | 21 | |
|---|
| 32 | 22 | #if defined(CONFIG_X86_32) |
|---|
| 33 | 23 | #define ia32_sys_call_table sys_call_table |
|---|
| 34 | | -#define __NR_syscall_compat_max __NR_syscall_max |
|---|
| 35 | | -#define IA32_NR_syscalls NR_syscalls |
|---|
| 36 | 24 | #endif |
|---|
| 37 | 25 | |
|---|
| 38 | 26 | #if defined(CONFIG_IA32_EMULATION) |
|---|
| 39 | 27 | extern const sys_call_ptr_t ia32_sys_call_table[]; |
|---|
| 28 | +#endif |
|---|
| 29 | + |
|---|
| 30 | +#ifdef CONFIG_X86_X32_ABI |
|---|
| 31 | +extern const sys_call_ptr_t x32_sys_call_table[]; |
|---|
| 40 | 32 | #endif |
|---|
| 41 | 33 | |
|---|
| 42 | 34 | /* |
|---|
| .. | .. |
|---|
| 91 | 83 | |
|---|
| 92 | 84 | static inline void syscall_get_arguments(struct task_struct *task, |
|---|
| 93 | 85 | struct pt_regs *regs, |
|---|
| 94 | | - unsigned int i, unsigned int n, |
|---|
| 95 | 86 | unsigned long *args) |
|---|
| 96 | 87 | { |
|---|
| 97 | | - BUG_ON(i + n > 6); |
|---|
| 98 | | - memcpy(args, ®s->bx + i, n * sizeof(args[0])); |
|---|
| 88 | + memcpy(args, ®s->bx, 6 * sizeof(args[0])); |
|---|
| 99 | 89 | } |
|---|
| 100 | 90 | |
|---|
| 101 | 91 | static inline void syscall_set_arguments(struct task_struct *task, |
|---|
| .. | .. |
|---|
| 107 | 97 | memcpy(®s->bx + i, args, n * sizeof(args[0])); |
|---|
| 108 | 98 | } |
|---|
| 109 | 99 | |
|---|
| 110 | | -static inline int syscall_get_arch(void) |
|---|
| 100 | +static inline int syscall_get_arch(struct task_struct *task) |
|---|
| 111 | 101 | { |
|---|
| 112 | 102 | return AUDIT_ARCH_I386; |
|---|
| 113 | 103 | } |
|---|
| .. | .. |
|---|
| 116 | 106 | |
|---|
| 117 | 107 | static inline void syscall_get_arguments(struct task_struct *task, |
|---|
| 118 | 108 | struct pt_regs *regs, |
|---|
| 119 | | - unsigned int i, unsigned int n, |
|---|
| 120 | 109 | unsigned long *args) |
|---|
| 121 | 110 | { |
|---|
| 122 | 111 | # ifdef CONFIG_IA32_EMULATION |
|---|
| 123 | | - if (task->thread_info.status & TS_COMPAT) |
|---|
| 124 | | - switch (i) { |
|---|
| 125 | | - case 0: |
|---|
| 126 | | - if (!n--) break; |
|---|
| 127 | | - *args++ = regs->bx; |
|---|
| 128 | | - case 1: |
|---|
| 129 | | - if (!n--) break; |
|---|
| 130 | | - *args++ = regs->cx; |
|---|
| 131 | | - case 2: |
|---|
| 132 | | - if (!n--) break; |
|---|
| 133 | | - *args++ = regs->dx; |
|---|
| 134 | | - case 3: |
|---|
| 135 | | - if (!n--) break; |
|---|
| 136 | | - *args++ = regs->si; |
|---|
| 137 | | - case 4: |
|---|
| 138 | | - if (!n--) break; |
|---|
| 139 | | - *args++ = regs->di; |
|---|
| 140 | | - case 5: |
|---|
| 141 | | - if (!n--) break; |
|---|
| 142 | | - *args++ = regs->bp; |
|---|
| 143 | | - case 6: |
|---|
| 144 | | - if (!n--) break; |
|---|
| 145 | | - default: |
|---|
| 146 | | - BUG(); |
|---|
| 147 | | - break; |
|---|
| 148 | | - } |
|---|
| 149 | | - else |
|---|
| 112 | + if (task->thread_info.status & TS_COMPAT) { |
|---|
| 113 | + *args++ = regs->bx; |
|---|
| 114 | + *args++ = regs->cx; |
|---|
| 115 | + *args++ = regs->dx; |
|---|
| 116 | + *args++ = regs->si; |
|---|
| 117 | + *args++ = regs->di; |
|---|
| 118 | + *args = regs->bp; |
|---|
| 119 | + } else |
|---|
| 150 | 120 | # endif |
|---|
| 151 | | - switch (i) { |
|---|
| 152 | | - case 0: |
|---|
| 153 | | - if (!n--) break; |
|---|
| 154 | | - *args++ = regs->di; |
|---|
| 155 | | - case 1: |
|---|
| 156 | | - if (!n--) break; |
|---|
| 157 | | - *args++ = regs->si; |
|---|
| 158 | | - case 2: |
|---|
| 159 | | - if (!n--) break; |
|---|
| 160 | | - *args++ = regs->dx; |
|---|
| 161 | | - case 3: |
|---|
| 162 | | - if (!n--) break; |
|---|
| 163 | | - *args++ = regs->r10; |
|---|
| 164 | | - case 4: |
|---|
| 165 | | - if (!n--) break; |
|---|
| 166 | | - *args++ = regs->r8; |
|---|
| 167 | | - case 5: |
|---|
| 168 | | - if (!n--) break; |
|---|
| 169 | | - *args++ = regs->r9; |
|---|
| 170 | | - case 6: |
|---|
| 171 | | - if (!n--) break; |
|---|
| 172 | | - default: |
|---|
| 173 | | - BUG(); |
|---|
| 174 | | - break; |
|---|
| 175 | | - } |
|---|
| 121 | + { |
|---|
| 122 | + *args++ = regs->di; |
|---|
| 123 | + *args++ = regs->si; |
|---|
| 124 | + *args++ = regs->dx; |
|---|
| 125 | + *args++ = regs->r10; |
|---|
| 126 | + *args++ = regs->r8; |
|---|
| 127 | + *args = regs->r9; |
|---|
| 128 | + } |
|---|
| 176 | 129 | } |
|---|
| 177 | 130 | |
|---|
| 178 | 131 | static inline void syscall_set_arguments(struct task_struct *task, |
|---|
| 179 | 132 | struct pt_regs *regs, |
|---|
| 180 | | - unsigned int i, unsigned int n, |
|---|
| 181 | 133 | const unsigned long *args) |
|---|
| 182 | 134 | { |
|---|
| 183 | 135 | # ifdef CONFIG_IA32_EMULATION |
|---|
| 184 | | - if (task->thread_info.status & TS_COMPAT) |
|---|
| 185 | | - switch (i) { |
|---|
| 186 | | - case 0: |
|---|
| 187 | | - if (!n--) break; |
|---|
| 188 | | - regs->bx = *args++; |
|---|
| 189 | | - case 1: |
|---|
| 190 | | - if (!n--) break; |
|---|
| 191 | | - regs->cx = *args++; |
|---|
| 192 | | - case 2: |
|---|
| 193 | | - if (!n--) break; |
|---|
| 194 | | - regs->dx = *args++; |
|---|
| 195 | | - case 3: |
|---|
| 196 | | - if (!n--) break; |
|---|
| 197 | | - regs->si = *args++; |
|---|
| 198 | | - case 4: |
|---|
| 199 | | - if (!n--) break; |
|---|
| 200 | | - regs->di = *args++; |
|---|
| 201 | | - case 5: |
|---|
| 202 | | - if (!n--) break; |
|---|
| 203 | | - regs->bp = *args++; |
|---|
| 204 | | - case 6: |
|---|
| 205 | | - if (!n--) break; |
|---|
| 206 | | - default: |
|---|
| 207 | | - BUG(); |
|---|
| 208 | | - break; |
|---|
| 209 | | - } |
|---|
| 210 | | - else |
|---|
| 136 | + if (task->thread_info.status & TS_COMPAT) { |
|---|
| 137 | + regs->bx = *args++; |
|---|
| 138 | + regs->cx = *args++; |
|---|
| 139 | + regs->dx = *args++; |
|---|
| 140 | + regs->si = *args++; |
|---|
| 141 | + regs->di = *args++; |
|---|
| 142 | + regs->bp = *args; |
|---|
| 143 | + } else |
|---|
| 211 | 144 | # endif |
|---|
| 212 | | - switch (i) { |
|---|
| 213 | | - case 0: |
|---|
| 214 | | - if (!n--) break; |
|---|
| 215 | | - regs->di = *args++; |
|---|
| 216 | | - case 1: |
|---|
| 217 | | - if (!n--) break; |
|---|
| 218 | | - regs->si = *args++; |
|---|
| 219 | | - case 2: |
|---|
| 220 | | - if (!n--) break; |
|---|
| 221 | | - regs->dx = *args++; |
|---|
| 222 | | - case 3: |
|---|
| 223 | | - if (!n--) break; |
|---|
| 224 | | - regs->r10 = *args++; |
|---|
| 225 | | - case 4: |
|---|
| 226 | | - if (!n--) break; |
|---|
| 227 | | - regs->r8 = *args++; |
|---|
| 228 | | - case 5: |
|---|
| 229 | | - if (!n--) break; |
|---|
| 230 | | - regs->r9 = *args++; |
|---|
| 231 | | - case 6: |
|---|
| 232 | | - if (!n--) break; |
|---|
| 233 | | - default: |
|---|
| 234 | | - BUG(); |
|---|
| 235 | | - break; |
|---|
| 236 | | - } |
|---|
| 145 | + { |
|---|
| 146 | + regs->di = *args++; |
|---|
| 147 | + regs->si = *args++; |
|---|
| 148 | + regs->dx = *args++; |
|---|
| 149 | + regs->r10 = *args++; |
|---|
| 150 | + regs->r8 = *args++; |
|---|
| 151 | + regs->r9 = *args; |
|---|
| 152 | + } |
|---|
| 237 | 153 | } |
|---|
| 238 | 154 | |
|---|
| 239 | | -static inline int syscall_get_arch(void) |
|---|
| 155 | +static inline int syscall_get_arch(struct task_struct *task) |
|---|
| 240 | 156 | { |
|---|
| 241 | 157 | /* x32 tasks should be considered AUDIT_ARCH_X86_64. */ |
|---|
| 242 | | - return in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; |
|---|
| 158 | + return (IS_ENABLED(CONFIG_IA32_EMULATION) && |
|---|
| 159 | + task->thread_info.status & TS_COMPAT) |
|---|
| 160 | + ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; |
|---|
| 243 | 161 | } |
|---|
| 162 | + |
|---|
| 163 | +void do_syscall_64(unsigned long nr, struct pt_regs *regs); |
|---|
| 164 | +void do_int80_syscall_32(struct pt_regs *regs); |
|---|
| 165 | +long do_fast_syscall_32(struct pt_regs *regs); |
|---|
| 166 | + |
|---|
| 244 | 167 | #endif /* CONFIG_X86_32 */ |
|---|
| 245 | 168 | |
|---|
| 246 | 169 | #endif /* _ASM_X86_SYSCALL_H */ |
|---|