Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

syscalls: Remove start and number from syscall_get_arguments() args

At Linux Plumbers, Andy Lutomirski approached me and pointed out that the
function call syscall_get_arguments() implemented in x86 was horribly
written and not optimized for the standard case of passing in 0 and 6 for
the starting index and the number of system calls to get. When looking at
all the users of this function, I discovered that all instances pass in only
0 and 6 for these arguments. Instead of having this function handle
different cases that are never used, simply rewrite it to return the first 6
arguments of a system call.

This should help out the performance of tracing system calls by ptrace,
ftrace and perf.

Link: http://lkml.kernel.org/r/20161107213233.754809394@goodmis.org

Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Dominik Brodowski <linux@dominikbrodowski.net>
Cc: Dave Martin <dave.martin@arm.com>
Cc: "Dmitry V. Levin" <ldv@altlinux.org>
Cc: x86@kernel.org
Cc: linux-snps-arc@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-c6x-dev@linux-c6x.org
Cc: uclinux-h8-devel@lists.sourceforge.jp
Cc: linux-hexagon@vger.kernel.org
Cc: linux-ia64@vger.kernel.org
Cc: linux-mips@vger.kernel.org
Cc: nios2-dev@lists.rocketboards.org
Cc: openrisc@lists.librecores.org
Cc: linux-parisc@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-riscv@lists.infradead.org
Cc: linux-s390@vger.kernel.org
Cc: linux-sh@vger.kernel.org
Cc: sparclinux@vger.kernel.org
Cc: linux-um@lists.infradead.org
Cc: linux-xtensa@linux-xtensa.org
Cc: linux-arch@vger.kernel.org
Acked-by: Paul Burton <paul.burton@mips.com> # MIPS parts
Acked-by: Max Filippov <jcmvbkbc@gmail.com> # For xtensa changes
Acked-by: Will Deacon <will.deacon@arm.com> # For the arm64 bits
Reviewed-by: Thomas Gleixner <tglx@linutronix.de> # for x86
Reviewed-by: Dmitry V. Levin <ldv@altlinux.org>
Reported-by: Andy Lutomirski <luto@amacapital.net>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>

+113 -378
+3 -4
arch/arc/include/asm/syscall.h
··· 55 55 */ 56 56 static inline void 57 57 syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, 58 - unsigned int i, unsigned int n, unsigned long *args) 58 + unsigned long *args) 59 59 { 60 60 unsigned long *inside_ptregs = &(regs->r0); 61 - inside_ptregs -= i; 62 - 63 - BUG_ON((i + n) > 6); 61 + unsigned int n = 6; 62 + unsigned int i = 0; 64 63 65 64 while (n--) { 66 65 args[i++] = (*inside_ptregs);
+3 -20
arch/arm/include/asm/syscall.h
··· 55 55 56 56 static inline void syscall_get_arguments(struct task_struct *task, 57 57 struct pt_regs *regs, 58 - unsigned int i, unsigned int n, 59 58 unsigned long *args) 60 59 { 61 - if (n == 0) 62 - return; 60 + args[0] = regs->ARM_ORIG_r0; 61 + args++; 63 62 64 - if (i + n > SYSCALL_MAX_ARGS) { 65 - unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i; 66 - unsigned int n_bad = n + i - SYSCALL_MAX_ARGS; 67 - pr_warn("%s called with max args %d, handling only %d\n", 68 - __func__, i + n, SYSCALL_MAX_ARGS); 69 - memset(args_bad, 0, n_bad * sizeof(args[0])); 70 - n = SYSCALL_MAX_ARGS - i; 71 - } 72 - 73 - if (i == 0) { 74 - args[0] = regs->ARM_ORIG_r0; 75 - args++; 76 - i++; 77 - n--; 78 - } 79 - 80 - memcpy(args, &regs->ARM_r0 + i, n * sizeof(args[0])); 63 + memcpy(args, &regs->ARM_r0 + 1, 5 * sizeof(args[0])); 81 64 } 82 65 83 66 static inline void syscall_set_arguments(struct task_struct *task,
+3 -19
arch/arm64/include/asm/syscall.h
··· 65 65 66 66 static inline void syscall_get_arguments(struct task_struct *task, 67 67 struct pt_regs *regs, 68 - unsigned int i, unsigned int n, 69 68 unsigned long *args) 70 69 { 71 - if (n == 0) 72 - return; 70 + args[0] = regs->orig_x0; 71 + args++; 73 72 74 - if (i + n > SYSCALL_MAX_ARGS) { 75 - unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i; 76 - unsigned int n_bad = n + i - SYSCALL_MAX_ARGS; 77 - pr_warning("%s called with max args %d, handling only %d\n", 78 - __func__, i + n, SYSCALL_MAX_ARGS); 79 - memset(args_bad, 0, n_bad * sizeof(args[0])); 80 - } 81 - 82 - if (i == 0) { 83 - args[0] = regs->orig_x0; 84 - args++; 85 - i++; 86 - n--; 87 - } 88 - 89 - memcpy(args, &regs->regs[i], n * sizeof(args[0])); 73 + memcpy(args, &regs->regs[1], 5 * sizeof(args[0])); 90 74 } 91 75 92 76 static inline void syscall_set_arguments(struct task_struct *task,
+8 -33
arch/c6x/include/asm/syscall.h
··· 46 46 } 47 47 48 48 static inline void syscall_get_arguments(struct task_struct *task, 49 - struct pt_regs *regs, unsigned int i, 50 - unsigned int n, unsigned long *args) 49 + struct pt_regs *regs, 50 + unsigned long *args) 51 51 { 52 - switch (i) { 53 - case 0: 54 - if (!n--) 55 - break; 56 - *args++ = regs->a4; 57 - case 1: 58 - if (!n--) 59 - break; 60 - *args++ = regs->b4; 61 - case 2: 62 - if (!n--) 63 - break; 64 - *args++ = regs->a6; 65 - case 3: 66 - if (!n--) 67 - break; 68 - *args++ = regs->b6; 69 - case 4: 70 - if (!n--) 71 - break; 72 - *args++ = regs->a8; 73 - case 5: 74 - if (!n--) 75 - break; 76 - *args++ = regs->b8; 77 - case 6: 78 - if (!n--) 79 - break; 80 - default: 81 - BUG(); 82 - } 52 + *args++ = regs->a4; 53 + *args++ = regs->b4; 54 + *args++ = regs->a6; 55 + *args++ = regs->b6; 56 + *args++ = regs->a8; 57 + *args = regs->b8; 83 58 } 84 59 85 60 static inline void syscall_set_arguments(struct task_struct *task,
+4 -10
arch/csky/include/asm/syscall.h
··· 43 43 44 44 static inline void 45 45 syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, 46 - unsigned int i, unsigned int n, unsigned long *args) 46 + unsigned long *args) 47 47 { 48 - BUG_ON(i + n > 6); 49 - if (i == 0) { 50 - args[0] = regs->orig_a0; 51 - args++; 52 - n--; 53 - } else { 54 - i--; 55 - } 56 - memcpy(args, &regs->a1 + i, n * sizeof(args[0])); 48 + args[0] = regs->orig_a0; 49 + args++; 50 + memcpy(args, &regs->a1, 5 * sizeof(args[0])); 57 51 } 58 52 59 53 static inline void
+7 -27
arch/h8300/include/asm/syscall.h
··· 17 17 18 18 static inline void 19 19 syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, 20 - unsigned int i, unsigned int n, unsigned long *args) 20 + unsigned long *args) 21 21 { 22 - BUG_ON(i + n > 6); 23 - 24 - while (n > 0) { 25 - switch (i) { 26 - case 0: 27 - *args++ = regs->er1; 28 - break; 29 - case 1: 30 - *args++ = regs->er2; 31 - break; 32 - case 2: 33 - *args++ = regs->er3; 34 - break; 35 - case 3: 36 - *args++ = regs->er4; 37 - break; 38 - case 4: 39 - *args++ = regs->er5; 40 - break; 41 - case 5: 42 - *args++ = regs->er6; 43 - break; 44 - } 45 - i++; 46 - n--; 47 - } 22 + *args++ = regs->er1; 23 + *args++ = regs->er2; 24 + *args++ = regs->er3; 25 + *args++ = regs->er4; 26 + *args++ = regs->er5; 27 + *args = regs->er6; 48 28 } 49 29 50 30
+1 -3
arch/hexagon/include/asm/syscall.h
··· 37 37 38 38 static inline void syscall_get_arguments(struct task_struct *task, 39 39 struct pt_regs *regs, 40 - unsigned int i, unsigned int n, 41 40 unsigned long *args) 42 41 { 43 - BUG_ON(i + n > 6); 44 - memcpy(args, &(&regs->r00)[i], n * sizeof(args[0])); 42 + memcpy(args, &(&regs->r00)[0], 6 * sizeof(args[0])); 45 43 } 46 44 #endif
+1 -4
arch/ia64/include/asm/syscall.h
··· 63 63 unsigned long *args, int rw); 64 64 static inline void syscall_get_arguments(struct task_struct *task, 65 65 struct pt_regs *regs, 66 - unsigned int i, unsigned int n, 67 66 unsigned long *args) 68 67 { 69 - BUG_ON(i + n > 6); 70 - 71 - ia64_syscall_get_set_arguments(task, regs, i, n, args, 0); 68 + ia64_syscall_get_set_arguments(task, regs, 0, 6, args, 0); 72 69 } 73 70 74 71 static inline void syscall_set_arguments(struct task_struct *task,
+3 -1
arch/microblaze/include/asm/syscall.h
··· 82 82 83 83 static inline void syscall_get_arguments(struct task_struct *task, 84 84 struct pt_regs *regs, 85 - unsigned int i, unsigned int n, 86 85 unsigned long *args) 87 86 { 87 + unsigned int i = 0; 88 + unsigned int n = 6; 89 + 88 90 while (n--) 89 91 *args++ = microblaze_get_syscall_arg(regs, i++); 90 92 }
+2 -1
arch/mips/include/asm/syscall.h
··· 116 116 117 117 static inline void syscall_get_arguments(struct task_struct *task, 118 118 struct pt_regs *regs, 119 - unsigned int i, unsigned int n, 120 119 unsigned long *args) 121 120 { 121 + unsigned int i = 0; 122 + unsigned int n = 6; 122 123 int ret; 123 124 124 125 /* O32 ABI syscall() */
+1 -1
arch/mips/kernel/ptrace.c
··· 1419 1419 1420 1420 sd.nr = syscall; 1421 1421 sd.arch = syscall_get_arch(); 1422 - syscall_get_arguments(current, regs, 0, 6, args); 1422 + syscall_get_arguments(current, regs, args); 1423 1423 for (i = 0; i < 6; i++) 1424 1424 sd.args[i] = args[i]; 1425 1425 sd.instruction_pointer = KSTK_EIP(current);
+6 -27
arch/nds32/include/asm/syscall.h
··· 108 108 * syscall_get_arguments - extract system call parameter values 109 109 * @task: task of interest, must be blocked 110 110 * @regs: task_pt_regs() of @task 111 - * @i: argument index [0,5] 112 - * @n: number of arguments; n+i must be [1,6]. 113 111 * @args: array filled with argument values 114 112 * 115 - * Fetches @n arguments to the system call starting with the @i'th argument 116 - * (from 0 through 5). Argument @i is stored in @args[0], and so on. 117 - * An arch inline version is probably optimal when @i and @n are constants. 113 + * Fetches 6 arguments to the system call (from 0 through 5). The first 114 + * argument is stored in @args[0], and so on. 118 115 * 119 116 * It's only valid to call this when @task is stopped for tracing on 120 117 * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 121 - * It's invalid to call this with @i + @n > 6; we only support system calls 122 - * taking up to 6 arguments. 123 118 */ 124 119 #define SYSCALL_MAX_ARGS 6 125 120 void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, 126 - unsigned int i, unsigned int n, unsigned long *args) 121 + unsigned long *args) 127 122 { 128 - if (n == 0) 129 - return; 130 - if (i + n > SYSCALL_MAX_ARGS) { 131 - unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i; 132 - unsigned int n_bad = n + i - SYSCALL_MAX_ARGS; 133 - pr_warning("%s called with max args %d, handling only %d\n", 134 - __func__, i + n, SYSCALL_MAX_ARGS); 135 - memset(args_bad, 0, n_bad * sizeof(args[0])); 136 - memset(args_bad, 0, n_bad * sizeof(args[0])); 137 - } 138 - 139 - if (i == 0) { 140 - args[0] = regs->orig_r0; 141 - args++; 142 - i++; 143 - n--; 144 - } 145 - 146 - memcpy(args, &regs->uregs[0] + i, n * sizeof(args[0])); 123 + args[0] = regs->orig_r0; 124 + args++; 125 + memcpy(args, &regs->uregs[0] + 1, 5 * sizeof(args[0])); 147 126 } 148 127 149 128 /**
+7 -35
arch/nios2/include/asm/syscall.h
··· 58 58 } 59 59 60 60 static inline void syscall_get_arguments(struct task_struct *task, 61 - struct pt_regs *regs, unsigned int i, unsigned int n, 62 - unsigned long *args) 61 + struct pt_regs *regs, unsigned long *args) 63 62 { 64 - BUG_ON(i + n > 6); 65 - 66 - switch (i) { 67 - case 0: 68 - if (!n--) 69 - break; 70 - *args++ = regs->r4; 71 - case 1: 72 - if (!n--) 73 - break; 74 - *args++ = regs->r5; 75 - case 2: 76 - if (!n--) 77 - break; 78 - *args++ = regs->r6; 79 - case 3: 80 - if (!n--) 81 - break; 82 - *args++ = regs->r7; 83 - case 4: 84 - if (!n--) 85 - break; 86 - *args++ = regs->r8; 87 - case 5: 88 - if (!n--) 89 - break; 90 - *args++ = regs->r9; 91 - case 6: 92 - if (!n--) 93 - break; 94 - default: 95 - BUG(); 96 - } 63 + *args++ = regs->r4; 64 + *args++ = regs->r5; 65 + *args++ = regs->r6; 66 + *args++ = regs->r7; 67 + *args++ = regs->r8; 68 + *args = regs->r9; 97 69 } 98 70 99 71 static inline void syscall_set_arguments(struct task_struct *task,
+2 -4
arch/openrisc/include/asm/syscall.h
··· 56 56 57 57 static inline void 58 58 syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, 59 - unsigned int i, unsigned int n, unsigned long *args) 59 + unsigned long *args) 60 60 { 61 - BUG_ON(i + n > 6); 62 - 63 - memcpy(args, &regs->gpr[3 + i], n * sizeof(args[0])); 61 + memcpy(args, &regs->gpr[3], 6 * sizeof(args[0])); 64 62 } 65 63 66 64 static inline void
+8 -22
arch/parisc/include/asm/syscall.h
··· 18 18 } 19 19 20 20 static inline void syscall_get_arguments(struct task_struct *tsk, 21 - struct pt_regs *regs, unsigned int i, 22 - unsigned int n, unsigned long *args) 21 + struct pt_regs *regs, 22 + unsigned long *args) 23 23 { 24 - BUG_ON(i); 25 - 26 - switch (n) { 27 - case 6: 28 - args[5] = regs->gr[21]; 29 - case 5: 30 - args[4] = regs->gr[22]; 31 - case 4: 32 - args[3] = regs->gr[23]; 33 - case 3: 34 - args[2] = regs->gr[24]; 35 - case 2: 36 - args[1] = regs->gr[25]; 37 - case 1: 38 - args[0] = regs->gr[26]; 39 - case 0: 40 - break; 41 - default: 42 - BUG(); 43 - } 24 + args[5] = regs->gr[21]; 25 + args[4] = regs->gr[22]; 26 + args[3] = regs->gr[23]; 27 + args[2] = regs->gr[24]; 28 + args[1] = regs->gr[25]; 29 + args[0] = regs->gr[26]; 44 30 } 45 31 46 32 static inline long syscall_get_return_value(struct task_struct *task,
+3 -5
arch/powerpc/include/asm/syscall.h
··· 65 65 66 66 static inline void syscall_get_arguments(struct task_struct *task, 67 67 struct pt_regs *regs, 68 - unsigned int i, unsigned int n, 69 68 unsigned long *args) 70 69 { 71 70 unsigned long val, mask = -1UL; 72 - 73 - BUG_ON(i + n > 6); 71 + unsigned int n = 6; 74 72 75 73 #ifdef CONFIG_COMPAT 76 74 if (test_tsk_thread_flag(task, TIF_32BIT)) 77 75 mask = 0xffffffff; 78 76 #endif 79 77 while (n--) { 80 - if (n == 0 && i == 0) 78 + if (n == 0) 81 79 val = regs->orig_gpr3; 82 80 else 83 - val = regs->gpr[3 + i + n]; 81 + val = regs->gpr[3 + n]; 84 82 85 83 args[n] = val & mask; 86 84 }
+3 -10
arch/riscv/include/asm/syscall.h
··· 72 72 73 73 static inline void syscall_get_arguments(struct task_struct *task, 74 74 struct pt_regs *regs, 75 - unsigned int i, unsigned int n, 76 75 unsigned long *args) 77 76 { 78 - BUG_ON(i + n > 6); 79 - if (i == 0) { 80 - args[0] = regs->orig_a0; 81 - args++; 82 - n--; 83 - } else { 84 - i--; 85 - } 86 - memcpy(args, &regs->a1 + i, n * sizeof(args[0])); 77 + args[0] = regs->orig_a0; 78 + args++; 79 + memcpy(args, &regs->a1, 5 * sizeof(args[0])); 87 80 } 88 81 89 82 static inline void syscall_set_arguments(struct task_struct *task,
+5 -12
arch/s390/include/asm/syscall.h
··· 56 56 57 57 static inline void syscall_get_arguments(struct task_struct *task, 58 58 struct pt_regs *regs, 59 - unsigned int i, unsigned int n, 60 59 unsigned long *args) 61 60 { 62 61 unsigned long mask = -1UL; 62 + unsigned int n = 6; 63 63 64 - /* 65 - * No arguments for this syscall, there's nothing to do. 66 - */ 67 - if (!n) 68 - return; 69 - 70 - BUG_ON(i + n > 6); 71 64 #ifdef CONFIG_COMPAT 72 65 if (test_tsk_thread_flag(task, TIF_31BIT)) 73 66 mask = 0xffffffff; 74 67 #endif 75 68 while (n-- > 0) 76 - if (i + n > 0) 77 - args[n] = regs->gprs[2 + i + n] & mask; 78 - if (i == 0) 79 - args[0] = regs->orig_gpr2 & mask; 69 + if (n > 0) 70 + args[n] = regs->gprs[2 + n] & mask; 71 + 72 + args[0] = regs->orig_gpr2 & mask; 80 73 } 81 74 82 75 static inline void syscall_set_arguments(struct task_struct *task,
+6 -20
arch/sh/include/asm/syscall_32.h
··· 48 48 49 49 static inline void syscall_get_arguments(struct task_struct *task, 50 50 struct pt_regs *regs, 51 - unsigned int i, unsigned int n, 52 51 unsigned long *args) 53 52 { 54 - /* 55 - * Do this simply for now. If we need to start supporting 56 - * fetching arguments from arbitrary indices, this will need some 57 - * extra logic. Presently there are no in-tree users that depend 58 - * on this behaviour. 59 - */ 60 - BUG_ON(i); 61 53 62 54 /* Argument pattern is: R4, R5, R6, R7, R0, R1 */ 63 - switch (n) { 64 - case 6: args[5] = regs->regs[1]; 65 - case 5: args[4] = regs->regs[0]; 66 - case 4: args[3] = regs->regs[7]; 67 - case 3: args[2] = regs->regs[6]; 68 - case 2: args[1] = regs->regs[5]; 69 - case 1: args[0] = regs->regs[4]; 70 - case 0: 71 - break; 72 - default: 73 - BUG(); 74 - } 55 + args[5] = regs->regs[1]; 56 + args[4] = regs->regs[0]; 57 + args[3] = regs->regs[7]; 58 + args[2] = regs->regs[6]; 59 + args[1] = regs->regs[5]; 60 + args[0] = regs->regs[4]; 75 61 } 76 62 77 63 static inline void syscall_set_arguments(struct task_struct *task,
+1 -3
arch/sh/include/asm/syscall_64.h
··· 47 47 48 48 static inline void syscall_get_arguments(struct task_struct *task, 49 49 struct pt_regs *regs, 50 - unsigned int i, unsigned int n, 51 50 unsigned long *args) 52 51 { 53 - BUG_ON(i + n > 6); 54 - memcpy(args, &regs->regs[2 + i], n * sizeof(args[0])); 52 + memcpy(args, &regs->regs[2], 6 * sizeof(args[0])); 55 53 } 56 54 57 55 static inline void syscall_set_arguments(struct task_struct *task,
+2 -2
arch/sparc/include/asm/syscall.h
··· 96 96 97 97 static inline void syscall_get_arguments(struct task_struct *task, 98 98 struct pt_regs *regs, 99 - unsigned int i, unsigned int n, 100 99 unsigned long *args) 101 100 { 102 101 int zero_extend = 0; 103 102 unsigned int j; 103 + unsigned int n = 6; 104 104 105 105 #ifdef CONFIG_SPARC64 106 106 if (test_tsk_thread_flag(task, TIF_32BIT)) ··· 108 108 #endif 109 109 110 110 for (j = 0; j < n; j++) { 111 - unsigned long val = regs->u_regs[UREG_I0 + i + j]; 111 + unsigned long val = regs->u_regs[UREG_I0 + j]; 112 112 113 113 if (zero_extend) 114 114 args[j] = (u32) val;
+6 -33
arch/um/include/asm/syscall-generic.h
··· 53 53 54 54 static inline void syscall_get_arguments(struct task_struct *task, 55 55 struct pt_regs *regs, 56 - unsigned int i, unsigned int n, 57 56 unsigned long *args) 58 57 { 59 58 const struct uml_pt_regs *r = &regs->regs; 60 59 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 - } 60 + *args++ = UPT_SYSCALL_ARG1(r); 61 + *args++ = UPT_SYSCALL_ARG2(r); 62 + *args++ = UPT_SYSCALL_ARG3(r); 63 + *args++ = UPT_SYSCALL_ARG4(r); 64 + *args++ = UPT_SYSCALL_ARG5(r); 65 + *args = UPT_SYSCALL_ARG6(r); 93 66 } 94 67 95 68 static inline void syscall_set_arguments(struct task_struct *task,
+17 -56
arch/x86/include/asm/syscall.h
··· 91 91 92 92 static inline void syscall_get_arguments(struct task_struct *task, 93 93 struct pt_regs *regs, 94 - unsigned int i, unsigned int n, 95 94 unsigned long *args) 96 95 { 97 - BUG_ON(i + n > 6); 98 - memcpy(args, &regs->bx + i, n * sizeof(args[0])); 96 + memcpy(args, &regs->bx, 6 * sizeof(args[0])); 99 97 } 100 98 101 99 static inline void syscall_set_arguments(struct task_struct *task, ··· 114 116 115 117 static inline void syscall_get_arguments(struct task_struct *task, 116 118 struct pt_regs *regs, 117 - unsigned int i, unsigned int n, 118 119 unsigned long *args) 119 120 { 120 121 # ifdef CONFIG_IA32_EMULATION 121 - if (task->thread_info.status & TS_COMPAT) 122 - switch (i) { 123 - case 0: 124 - if (!n--) break; 125 - *args++ = regs->bx; 126 - case 1: 127 - if (!n--) break; 128 - *args++ = regs->cx; 129 - case 2: 130 - if (!n--) break; 131 - *args++ = regs->dx; 132 - case 3: 133 - if (!n--) break; 134 - *args++ = regs->si; 135 - case 4: 136 - if (!n--) break; 137 - *args++ = regs->di; 138 - case 5: 139 - if (!n--) break; 140 - *args++ = regs->bp; 141 - case 6: 142 - if (!n--) break; 143 - default: 144 - BUG(); 145 - break; 146 - } 147 - else 122 + if (task->thread_info.status & TS_COMPAT) { 123 + *args++ = regs->bx; 124 + *args++ = regs->cx; 125 + *args++ = regs->dx; 126 + *args++ = regs->si; 127 + *args++ = regs->di; 128 + *args = regs->bp; 129 + } else 148 130 # endif 149 - switch (i) { 150 - case 0: 151 - if (!n--) break; 152 - *args++ = regs->di; 153 - case 1: 154 - if (!n--) break; 155 - *args++ = regs->si; 156 - case 2: 157 - if (!n--) break; 158 - *args++ = regs->dx; 159 - case 3: 160 - if (!n--) break; 161 - *args++ = regs->r10; 162 - case 4: 163 - if (!n--) break; 164 - *args++ = regs->r8; 165 - case 5: 166 - if (!n--) break; 167 - *args++ = regs->r9; 168 - case 6: 169 - if (!n--) break; 170 - default: 171 - BUG(); 172 - break; 173 - } 131 + { 132 + *args++ = regs->di; 133 + *args++ = regs->si; 134 + *args++ = regs->dx; 135 + *args++ = regs->r10; 136 + *args++ = regs->r8; 137 + *args = regs->r9; 138 + } 174 139 } 175 140 176 141 static inline void syscall_set_arguments(struct task_struct *task,
+3 -13
arch/xtensa/include/asm/syscall.h
··· 59 59 60 60 static inline void syscall_get_arguments(struct task_struct *task, 61 61 struct pt_regs *regs, 62 - unsigned int i, unsigned int n, 63 62 unsigned long *args) 64 63 { 65 64 static const unsigned int reg[] = XTENSA_SYSCALL_ARGUMENT_REGS; 66 - unsigned int j; 65 + unsigned int i; 67 66 68 - if (n == 0) 69 - return; 70 - 71 - WARN_ON_ONCE(i + n > SYSCALL_MAX_ARGS); 72 - 73 - for (j = 0; j < n; ++j) { 74 - if (i + j < SYSCALL_MAX_ARGS) 75 - args[j] = regs->areg[reg[i + j]]; 76 - else 77 - args[j] = 0; 78 - } 67 + for (i = 0; i < 6; ++i) 68 + args[i] = regs->areg[reg[i]]; 79 69 } 80 70 81 71 static inline void syscall_set_arguments(struct task_struct *task,
+3 -8
include/asm-generic/syscall.h
··· 105 105 * syscall_get_arguments - extract system call parameter values 106 106 * @task: task of interest, must be blocked 107 107 * @regs: task_pt_regs() of @task 108 - * @i: argument index [0,5] 109 - * @n: number of arguments; n+i must be [1,6]. 110 108 * @args: array filled with argument values 111 109 * 112 - * Fetches @n arguments to the system call starting with the @i'th argument 113 - * (from 0 through 5). Argument @i is stored in @args[0], and so on. 114 - * An arch inline version is probably optimal when @i and @n are constants. 110 + * Fetches 6 arguments to the system call. First argument is stored in 111 + * @args[0], and so on. 115 112 * 116 113 * It's only valid to call this when @task is stopped for tracing on 117 114 * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 118 - * It's invalid to call this with @i + @n > 6; we only support system calls 119 - * taking up to 6 arguments. 120 115 */ 121 116 void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, 122 - unsigned int i, unsigned int n, unsigned long *args); 117 + unsigned long *args); 123 118 124 119 /** 125 120 * syscall_set_arguments - change system call parameter value
+1 -1
include/trace/events/syscalls.h
··· 28 28 29 29 TP_fast_assign( 30 30 __entry->id = id; 31 - syscall_get_arguments(current, regs, 0, 6, __entry->args); 31 + syscall_get_arguments(current, regs, __entry->args); 32 32 ), 33 33 34 34 TP_printk("NR %ld (%lx, %lx, %lx, %lx, %lx, %lx)",
+1 -1
kernel/seccomp.c
··· 149 149 150 150 sd->nr = syscall_get_nr(task, regs); 151 151 sd->arch = syscall_get_arch(); 152 - syscall_get_arguments(task, regs, 0, 6, args); 152 + syscall_get_arguments(task, regs, args); 153 153 sd->args[0] = args[0]; 154 154 sd->args[1] = args[1]; 155 155 sd->args[2] = args[2];
+2 -2
kernel/trace/trace_syscalls.c
··· 348 348 349 349 entry = ring_buffer_event_data(event); 350 350 entry->nr = syscall_nr; 351 - syscall_get_arguments(current, regs, 0, 6, args); 351 + syscall_get_arguments(current, regs, args); 352 352 memcpy(entry->args, args, sizeof(unsigned long) * sys_data->nb_args); 353 353 354 354 event_trigger_unlock_commit(trace_file, buffer, event, entry, ··· 616 616 return; 617 617 618 618 rec->nr = syscall_nr; 619 - syscall_get_arguments(current, regs, 0, 6, args); 619 + syscall_get_arguments(current, regs, args); 620 620 memcpy(&rec->args, args, sizeof(unsigned long) * sys_data->nb_args); 621 621 622 622 if ((valid_prog_array &&
+1 -1
lib/syscall.c
··· 27 27 28 28 info->data.nr = syscall_get_nr(target, regs); 29 29 if (info->data.nr != -1L) 30 - syscall_get_arguments(target, regs, 0, 6, 30 + syscall_get_arguments(target, regs, 31 31 (unsigned long *)&info->data.args[0]); 32 32 33 33 put_task_stack(target);