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

Merge tag 'trace-5.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull syscall-get-arguments cleanup and fixes from Steven Rostedt:
"Andy Lutomirski approached me to tell me that the
syscall_get_arguments() implementation in x86 was horrible and gcc
certainly gets it wrong.

He said that since the tracepoints only pass in 0 and 6 for i and n
repectively, it should be optimized for that case. Inspecting the
kernel, I discovered that all users pass in 0 for i and only one file
passing in something other than 6 for the number of arguments. That
code happens to be my own code used for the special syscall tracing.

That can easily be converted to just using 0 and 6 as well, and only
copying what is needed. Which is probably the faster path anyway for
that case.

Along the way, a couple of real fixes came from this as the
syscall_get_arguments() function was incorrect for csky and riscv.

x86 has been optimized to for the new interface that removes the
variable number of arguments, but the other architectures could still
use some loving and take more advantage of the simpler interface"

* tag 'trace-5.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
syscalls: Remove start and number from syscall_set_arguments() args
syscalls: Remove start and number from syscall_get_arguments() args
csky: Fix syscall_get_arguments() and syscall_set_arguments()
riscv: Fix syscall_get_arguments() and syscall_set_arguments()
tracing/syscalls: Pass in hardcoded 6 into syscall_get_arguments()
ptrace: Remove maxargs from task_current_syscall()

+243 -718
+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);
+6 -37
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, 84 67 struct pt_regs *regs, 85 - unsigned int i, unsigned int n, 86 68 const unsigned long *args) 87 69 { 88 - if (n == 0) 89 - return; 70 + regs->ARM_ORIG_r0 = args[0]; 71 + args++; 90 72 91 - if (i + n > SYSCALL_MAX_ARGS) { 92 - pr_warn("%s called with max args %d, handling only %d\n", 93 - __func__, i + n, SYSCALL_MAX_ARGS); 94 - n = SYSCALL_MAX_ARGS - i; 95 - } 96 - 97 - if (i == 0) { 98 - regs->ARM_ORIG_r0 = args[0]; 99 - args++; 100 - i++; 101 - n--; 102 - } 103 - 104 - memcpy(&regs->ARM_r0 + i, args, n * sizeof(args[0])); 73 + memcpy(&regs->ARM_r0 + 1, args, 5 * sizeof(args[0])); 105 74 } 106 75 107 76 static inline int syscall_get_arch(void)
+6 -36
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, 93 77 struct pt_regs *regs, 94 - unsigned int i, unsigned int n, 95 78 const unsigned long *args) 96 79 { 97 - if (n == 0) 98 - return; 80 + regs->orig_x0 = args[0]; 81 + args++; 99 82 100 - if (i + n > SYSCALL_MAX_ARGS) { 101 - pr_warning("%s called with max args %d, handling only %d\n", 102 - __func__, i + n, SYSCALL_MAX_ARGS); 103 - n = SYSCALL_MAX_ARGS - i; 104 - } 105 - 106 - if (i == 0) { 107 - regs->orig_x0 = args[0]; 108 - args++; 109 - i++; 110 - n--; 111 - } 112 - 113 - memcpy(&regs->regs[i], args, n * sizeof(args[0])); 83 + memcpy(&regs->regs[1], args, 5 * sizeof(args[0])); 114 84 } 115 85 116 86 /*
+14 -65
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, 86 61 struct pt_regs *regs, 87 - unsigned int i, unsigned int n, 88 62 const unsigned long *args) 89 63 { 90 - switch (i) { 91 - case 0: 92 - if (!n--) 93 - break; 94 - regs->a4 = *args++; 95 - case 1: 96 - if (!n--) 97 - break; 98 - regs->b4 = *args++; 99 - case 2: 100 - if (!n--) 101 - break; 102 - regs->a6 = *args++; 103 - case 3: 104 - if (!n--) 105 - break; 106 - regs->b6 = *args++; 107 - case 4: 108 - if (!n--) 109 - break; 110 - regs->a8 = *args++; 111 - case 5: 112 - if (!n--) 113 - break; 114 - regs->a9 = *args++; 115 - case 6: 116 - if (!n) 117 - break; 118 - default: 119 - BUG(); 120 - } 64 + regs->a4 = *args++; 65 + regs->b4 = *args++; 66 + regs->a6 = *args++; 67 + regs->b6 = *args++; 68 + regs->a8 = *args++; 69 + regs->a9 = *args; 121 70 } 122 71 123 72 #endif /* __ASM_C6X_SYSCALLS_H */
+8 -18
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 - i++; 53 - n--; 54 - } 55 - memcpy(args, &regs->a1 + i * sizeof(regs->a1), n * sizeof(args[0])); 48 + args[0] = regs->orig_a0; 49 + args++; 50 + memcpy(args, &regs->a1, 5 * sizeof(args[0])); 56 51 } 57 52 58 53 static inline void 59 54 syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, 60 - unsigned int i, unsigned int n, const unsigned long *args) 55 + const unsigned long *args) 61 56 { 62 - BUG_ON(i + n > 6); 63 - if (i == 0) { 64 - regs->orig_a0 = args[0]; 65 - args++; 66 - i++; 67 - n--; 68 - } 69 - memcpy(&regs->a1 + i * sizeof(regs->a1), args, n * sizeof(regs->a0)); 57 + regs->orig_a0 = args[0]; 58 + args++; 59 + memcpy(&regs->a1, args, 5 * sizeof(regs->a1)); 70 60 } 71 61 72 62 static inline int
+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
+3 -10
arch/ia64/include/asm/syscall.h
··· 59 59 } 60 60 61 61 extern void ia64_syscall_get_set_arguments(struct task_struct *task, 62 - struct pt_regs *regs, unsigned int i, unsigned int n, 63 - unsigned long *args, int rw); 62 + struct pt_regs *regs, unsigned long *args, int rw); 64 63 static inline void syscall_get_arguments(struct task_struct *task, 65 64 struct pt_regs *regs, 66 - unsigned int i, unsigned int n, 67 65 unsigned long *args) 68 66 { 69 - BUG_ON(i + n > 6); 70 - 71 - ia64_syscall_get_set_arguments(task, regs, i, n, args, 0); 67 + ia64_syscall_get_set_arguments(task, regs, args, 0); 72 68 } 73 69 74 70 static inline void syscall_set_arguments(struct task_struct *task, 75 71 struct pt_regs *regs, 76 - unsigned int i, unsigned int n, 77 72 unsigned long *args) 78 73 { 79 - BUG_ON(i + n > 6); 80 - 81 - ia64_syscall_get_set_arguments(task, regs, i, n, args, 1); 74 + ia64_syscall_get_set_arguments(task, regs, args, 1); 82 75 } 83 76 84 77 static inline int syscall_get_arch(void)
+3 -4
arch/ia64/kernel/ptrace.c
··· 2179 2179 } 2180 2180 2181 2181 void ia64_syscall_get_set_arguments(struct task_struct *task, 2182 - struct pt_regs *regs, unsigned int i, unsigned int n, 2183 - unsigned long *args, int rw) 2182 + struct pt_regs *regs, unsigned long *args, int rw) 2184 2183 { 2185 2184 struct syscall_get_set_args data = { 2186 - .i = i, 2187 - .n = n, 2185 + .i = 0, 2186 + .n = 6, 2188 2187 .args = args, 2189 2188 .regs = regs, 2190 2189 .rw = rw,
+6 -2
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 } 91 93 92 94 static inline void syscall_set_arguments(struct task_struct *task, 93 95 struct pt_regs *regs, 94 - unsigned int i, unsigned int n, 95 96 const unsigned long *args) 96 97 { 98 + unsigned int i = 0; 99 + unsigned int n = 6; 100 + 97 101 while (n--) 98 102 microblaze_set_syscall_arg(regs, i++, *args++); 99 103 }
+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);
+11 -51
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 /** 150 129 * syscall_set_arguments - change system call parameter value 151 130 * @task: task of interest, must be in system call entry tracing 152 131 * @regs: task_pt_regs() of @task 153 - * @i: argument index [0,5] 154 - * @n: number of arguments; n+i must be [1,6]. 155 132 * @args: array of argument values to store 156 133 * 157 - * Changes @n arguments to the system call starting with the @i'th argument. 158 - * Argument @i gets value @args[0], and so on. 159 - * An arch inline version is probably optimal when @i and @n are constants. 134 + * Changes 6 arguments to the system call. The first argument gets value 135 + * @args[0], and so on. 160 136 * 161 137 * It's only valid to call this when @task is stopped for tracing on 162 138 * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 163 - * It's invalid to call this with @i + @n > 6; we only support system calls 164 - * taking up to 6 arguments. 165 139 */ 166 140 void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, 167 - unsigned int i, unsigned int n, 168 141 const unsigned long *args) 169 142 { 170 - if (n == 0) 171 - return; 143 + regs->orig_r0 = args[0]; 144 + args++; 172 145 173 - if (i + n > SYSCALL_MAX_ARGS) { 174 - pr_warn("%s called with max args %d, handling only %d\n", 175 - __func__, i + n, SYSCALL_MAX_ARGS); 176 - n = SYSCALL_MAX_ARGS - i; 177 - } 178 - 179 - if (i == 0) { 180 - regs->orig_r0 = args[0]; 181 - args++; 182 - i++; 183 - n--; 184 - } 185 - 186 - memcpy(&regs->uregs[0] + i, args, n * sizeof(args[0])); 146 + memcpy(&regs->uregs[0] + 1, args, 5 * sizeof(args[0])); 187 147 } 188 148 #endif /* _ASM_NDS32_SYSCALL_H */
+14 -70
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, 100 - struct pt_regs *regs, unsigned int i, unsigned int n, 101 - const unsigned long *args) 72 + struct pt_regs *regs, const unsigned long *args) 102 73 { 103 - BUG_ON(i + n > 6); 104 - 105 - switch (i) { 106 - case 0: 107 - if (!n--) 108 - break; 109 - regs->r4 = *args++; 110 - case 1: 111 - if (!n--) 112 - break; 113 - regs->r5 = *args++; 114 - case 2: 115 - if (!n--) 116 - break; 117 - regs->r6 = *args++; 118 - case 3: 119 - if (!n--) 120 - break; 121 - regs->r7 = *args++; 122 - case 4: 123 - if (!n--) 124 - break; 125 - regs->r8 = *args++; 126 - case 5: 127 - if (!n--) 128 - break; 129 - regs->r9 = *args++; 130 - case 6: 131 - if (!n) 132 - break; 133 - default: 134 - BUG(); 135 - } 74 + regs->r4 = *args++; 75 + regs->r5 = *args++; 76 + regs->r6 = *args++; 77 + regs->r7 = *args++; 78 + regs->r8 = *args++; 79 + regs->r9 = *args; 136 80 } 137 81 138 82 #endif
+4 -8
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 67 65 syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, 68 - unsigned int i, unsigned int n, const unsigned long *args) 66 + const unsigned long *args) 69 67 { 70 - BUG_ON(i + n > 6); 71 - 72 - memcpy(&regs->gpr[3 + i], args, n * sizeof(args[0])); 68 + memcpy(&regs->gpr[3], args, 6 * sizeof(args[0])); 73 69 } 74 70 75 71 static inline int syscall_get_arch(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,
+5 -10
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 } ··· 86 88 87 89 static inline void syscall_set_arguments(struct task_struct *task, 88 90 struct pt_regs *regs, 89 - unsigned int i, unsigned int n, 90 91 const unsigned long *args) 91 92 { 92 - BUG_ON(i + n > 6); 93 - memcpy(&regs->gpr[3 + i], args, n * sizeof(args[0])); 93 + memcpy(&regs->gpr[3], args, 6 * sizeof(args[0])); 94 94 95 95 /* Also copy the first argument into orig_gpr3 */ 96 - if (i == 0 && n > 0) 97 - regs->orig_gpr3 = args[0]; 96 + regs->orig_gpr3 = args[0]; 98 97 } 99 98 100 99 static inline int syscall_get_arch(void)
+6 -18
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 - i++; 83 - n--; 84 - } 85 - memcpy(args, &regs->a1 + i * sizeof(regs->a1), n * sizeof(args[0])); 77 + args[0] = regs->orig_a0; 78 + args++; 79 + memcpy(args, &regs->a1, 5 * sizeof(args[0])); 86 80 } 87 81 88 82 static inline void syscall_set_arguments(struct task_struct *task, 89 83 struct pt_regs *regs, 90 - unsigned int i, unsigned int n, 91 84 const unsigned long *args) 92 85 { 93 - BUG_ON(i + n > 6); 94 - if (i == 0) { 95 - regs->orig_a0 = args[0]; 96 - args++; 97 - i++; 98 - n--; 99 - } 100 - memcpy(&regs->a1 + i * sizeof(regs->a1), args, n * sizeof(regs->a0)); 86 + regs->orig_a0 = args[0]; 87 + args++; 88 + memcpy(&regs->a1, args, 5 * sizeof(regs->a1)); 101 89 } 102 90 103 91 static inline int syscall_get_arch(void)
+10 -18
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, 83 76 struct pt_regs *regs, 84 - unsigned int i, unsigned int n, 85 77 const unsigned long *args) 86 78 { 87 - BUG_ON(i + n > 6); 79 + unsigned int n = 6; 80 + 88 81 while (n-- > 0) 89 - if (i + n > 0) 90 - regs->gprs[2 + i + n] = args[n]; 91 - if (i == 0) 92 - regs->orig_gpr2 = args[0]; 82 + if (n > 0) 83 + regs->gprs[2 + n] = args[n]; 84 + regs->orig_gpr2 = args[0]; 93 85 } 94 86 95 87 static inline int syscall_get_arch(void)
+12 -35
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, 78 64 struct pt_regs *regs, 79 - unsigned int i, unsigned int n, 80 65 const unsigned long *args) 81 66 { 82 - /* Same note as above applies */ 83 - BUG_ON(i); 84 - 85 - switch (n) { 86 - case 6: regs->regs[1] = args[5]; 87 - case 5: regs->regs[0] = args[4]; 88 - case 4: regs->regs[7] = args[3]; 89 - case 3: regs->regs[6] = args[2]; 90 - case 2: regs->regs[5] = args[1]; 91 - case 1: regs->regs[4] = args[0]; 92 - break; 93 - default: 94 - BUG(); 95 - } 67 + regs->regs[1] = args[5]; 68 + regs->regs[0] = args[4]; 69 + regs->regs[7] = args[3]; 70 + regs->regs[6] = args[2]; 71 + regs->regs[5] = args[1]; 72 + regs->regs[4] = args[0]; 96 73 } 97 74 98 75 static inline int syscall_get_arch(void)
+2 -6
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, 58 56 struct pt_regs *regs, 59 - unsigned int i, unsigned int n, 60 57 const unsigned long *args) 61 58 { 62 - BUG_ON(i + n > 6); 63 - memcpy(&regs->regs[2 + i], args, n * sizeof(args[0])); 59 + memcpy(&regs->regs[2], args, 6 * sizeof(args[0])); 64 60 } 65 61 66 62 static inline int syscall_get_arch(void)
+5 -6
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; ··· 119 119 120 120 static inline void syscall_set_arguments(struct task_struct *task, 121 121 struct pt_regs *regs, 122 - unsigned int i, unsigned int n, 123 122 const unsigned long *args) 124 123 { 125 - unsigned int j; 124 + unsigned int i; 126 125 127 - for (j = 0; j < n; j++) 128 - regs->u_regs[UREG_I0 + i + j] = args[j]; 126 + for (i = 0; i < 6; i++) 127 + regs->u_regs[UREG_I0 + i] = args[i]; 129 128 } 130 129 131 130 static inline int syscall_get_arch(void)
+12 -66
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, 96 69 struct pt_regs *regs, 97 - unsigned int i, unsigned int n, 98 70 const unsigned long *args) 99 71 { 100 72 struct uml_pt_regs *r = &regs->regs; 101 73 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 - } 74 + UPT_SYSCALL_ARG1(r) = *args++; 75 + UPT_SYSCALL_ARG2(r) = *args++; 76 + UPT_SYSCALL_ARG3(r) = *args++; 77 + UPT_SYSCALL_ARG4(r) = *args++; 78 + UPT_SYSCALL_ARG5(r) = *args++; 79 + UPT_SYSCALL_ARG6(r) = *args; 134 80 } 135 81 136 82 /* See arch/x86/um/asm/syscall.h for syscall_get_arch() definition. */
+33 -109
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, 177 142 struct pt_regs *regs, 178 - unsigned int i, unsigned int n, 179 143 const unsigned long *args) 180 144 { 181 145 # ifdef CONFIG_IA32_EMULATION 182 - if (task->thread_info.status & TS_COMPAT) 183 - switch (i) { 184 - case 0: 185 - if (!n--) break; 186 - regs->bx = *args++; 187 - case 1: 188 - if (!n--) break; 189 - regs->cx = *args++; 190 - case 2: 191 - if (!n--) break; 192 - regs->dx = *args++; 193 - case 3: 194 - if (!n--) break; 195 - regs->si = *args++; 196 - case 4: 197 - if (!n--) break; 198 - regs->di = *args++; 199 - case 5: 200 - if (!n--) break; 201 - regs->bp = *args++; 202 - case 6: 203 - if (!n--) break; 204 - default: 205 - BUG(); 206 - break; 207 - } 208 - else 146 + if (task->thread_info.status & TS_COMPAT) { 147 + regs->bx = *args++; 148 + regs->cx = *args++; 149 + regs->dx = *args++; 150 + regs->si = *args++; 151 + regs->di = *args++; 152 + regs->bp = *args; 153 + } else 209 154 # endif 210 - switch (i) { 211 - case 0: 212 - if (!n--) break; 213 - regs->di = *args++; 214 - case 1: 215 - if (!n--) break; 216 - regs->si = *args++; 217 - case 2: 218 - if (!n--) break; 219 - regs->dx = *args++; 220 - case 3: 221 - if (!n--) break; 222 - regs->r10 = *args++; 223 - case 4: 224 - if (!n--) break; 225 - regs->r8 = *args++; 226 - case 5: 227 - if (!n--) break; 228 - regs->r9 = *args++; 229 - case 6: 230 - if (!n--) break; 231 - default: 232 - BUG(); 233 - break; 234 - } 155 + { 156 + regs->di = *args++; 157 + regs->si = *args++; 158 + regs->dx = *args++; 159 + regs->r10 = *args++; 160 + regs->r8 = *args++; 161 + regs->r9 = *args; 162 + } 235 163 } 236 164 237 165 static inline int syscall_get_arch(void)
+6 -27
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, 82 72 struct pt_regs *regs, 83 - unsigned int i, unsigned int n, 84 73 const unsigned long *args) 85 74 { 86 75 static const unsigned int reg[] = XTENSA_SYSCALL_ARGUMENT_REGS; 87 - unsigned int j; 76 + unsigned int i; 88 77 89 - if (n == 0) 90 - return; 91 - 92 - if (WARN_ON_ONCE(i + n > SYSCALL_MAX_ARGS)) { 93 - if (i < SYSCALL_MAX_ARGS) 94 - n = SYSCALL_MAX_ARGS - i; 95 - else 96 - return; 97 - } 98 - 99 - for (j = 0; j < n; ++j) 100 - regs->areg[reg[i + j]] = args[j]; 78 + for (i = 0; i < 6; ++i) 79 + regs->areg[reg[i]] = args[i]; 101 80 } 102 81 103 82 asmlinkage long xtensa_rt_sigreturn(struct pt_regs*);
+9 -8
fs/proc/base.c
··· 616 616 static int proc_pid_syscall(struct seq_file *m, struct pid_namespace *ns, 617 617 struct pid *pid, struct task_struct *task) 618 618 { 619 - long nr; 620 - unsigned long args[6], sp, pc; 619 + struct syscall_info info; 620 + u64 *args = &info.data.args[0]; 621 621 int res; 622 622 623 623 res = lock_trace(task); 624 624 if (res) 625 625 return res; 626 626 627 - if (task_current_syscall(task, &nr, args, 6, &sp, &pc)) 627 + if (task_current_syscall(task, &info)) 628 628 seq_puts(m, "running\n"); 629 - else if (nr < 0) 630 - seq_printf(m, "%ld 0x%lx 0x%lx\n", nr, sp, pc); 629 + else if (info.data.nr < 0) 630 + seq_printf(m, "%d 0x%llx 0x%llx\n", 631 + info.data.nr, info.sp, info.data.instruction_pointer); 631 632 else 632 633 seq_printf(m, 633 - "%ld 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", 634 - nr, 634 + "%d 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx\n", 635 + info.data.nr, 635 636 args[0], args[1], args[2], args[3], args[4], args[5], 636 - sp, pc); 637 + info.sp, info.data.instruction_pointer); 637 638 unlock_trace(task); 638 639 639 640 return 0;
+5 -16
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 126 121 * @task: task of interest, must be in system call entry tracing 127 122 * @regs: task_pt_regs() of @task 128 - * @i: argument index [0,5] 129 - * @n: number of arguments; n+i must be [1,6]. 130 123 * @args: array of argument values to store 131 124 * 132 - * Changes @n arguments to the system call starting with the @i'th argument. 133 - * Argument @i gets value @args[0], and so on. 134 - * An arch inline version is probably optimal when @i and @n are constants. 125 + * Changes 6 arguments to the system call. 126 + * The first argument gets value @args[0], and so on. 135 127 * 136 128 * It's only valid to call this when @task is stopped for tracing on 137 129 * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 138 - * It's invalid to call this with @i + @n > 6; we only support system calls 139 - * taking up to 6 arguments. 140 130 */ 141 131 void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, 142 - unsigned int i, unsigned int n, 143 132 const unsigned long *args); 144 133 145 134 /**
+8 -3
include/linux/ptrace.h
··· 9 9 #include <linux/bug.h> /* For BUG_ON. */ 10 10 #include <linux/pid_namespace.h> /* For task_active_pid_ns. */ 11 11 #include <uapi/linux/ptrace.h> 12 + #include <linux/seccomp.h> 13 + 14 + /* Add sp to seccomp_data, as seccomp is user API, we don't want to modify it */ 15 + struct syscall_info { 16 + __u64 sp; 17 + struct seccomp_data data; 18 + }; 12 19 13 20 extern int ptrace_access_vm(struct task_struct *tsk, unsigned long addr, 14 21 void *buf, int len, unsigned int gup_flags); ··· 414 407 #define current_user_stack_pointer() user_stack_pointer(current_pt_regs()) 415 408 #endif 416 409 417 - extern int task_current_syscall(struct task_struct *target, long *callno, 418 - unsigned long args[6], unsigned int maxargs, 419 - unsigned long *sp, unsigned long *pc); 410 + extern int task_current_syscall(struct task_struct *target, struct syscall_info *info); 420 411 421 412 extern void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact); 422 413 #endif
+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];
+6 -3
kernel/trace/trace_syscalls.c
··· 314 314 struct ring_buffer_event *event; 315 315 struct ring_buffer *buffer; 316 316 unsigned long irq_flags; 317 + unsigned long args[6]; 317 318 int pc; 318 319 int syscall_nr; 319 320 int size; ··· 348 347 349 348 entry = ring_buffer_event_data(event); 350 349 entry->nr = syscall_nr; 351 - syscall_get_arguments(current, regs, 0, sys_data->nb_args, entry->args); 350 + syscall_get_arguments(current, regs, args); 351 + memcpy(entry->args, args, sizeof(unsigned long) * sys_data->nb_args); 352 352 353 353 event_trigger_unlock_commit(trace_file, buffer, event, entry, 354 354 irq_flags, pc); ··· 585 583 struct syscall_metadata *sys_data; 586 584 struct syscall_trace_enter *rec; 587 585 struct hlist_head *head; 586 + unsigned long args[6]; 588 587 bool valid_prog_array; 589 588 int syscall_nr; 590 589 int rctx; ··· 616 613 return; 617 614 618 615 rec->nr = syscall_nr; 619 - syscall_get_arguments(current, regs, 0, sys_data->nb_args, 620 - (unsigned long *)&rec->args); 616 + syscall_get_arguments(current, regs, args); 617 + memcpy(&rec->args, args, sizeof(unsigned long) * sys_data->nb_args); 621 618 622 619 if ((valid_prog_array && 623 620 !perf_call_bpf_enter(sys_data->enter_event, regs, sys_data, rec)) ||
+25 -32
lib/syscall.c
··· 5 5 #include <linux/export.h> 6 6 #include <asm/syscall.h> 7 7 8 - static int collect_syscall(struct task_struct *target, long *callno, 9 - unsigned long args[6], unsigned int maxargs, 10 - unsigned long *sp, unsigned long *pc) 8 + static int collect_syscall(struct task_struct *target, struct syscall_info *info) 11 9 { 12 10 struct pt_regs *regs; 13 11 14 12 if (!try_get_task_stack(target)) { 15 13 /* Task has no stack, so the task isn't in a syscall. */ 16 - *sp = *pc = 0; 17 - *callno = -1; 14 + memset(info, 0, sizeof(*info)); 15 + info->data.nr = -1; 18 16 return 0; 19 17 } 20 18 ··· 22 24 return -EAGAIN; 23 25 } 24 26 25 - *sp = user_stack_pointer(regs); 26 - *pc = instruction_pointer(regs); 27 + info->sp = user_stack_pointer(regs); 28 + info->data.instruction_pointer = instruction_pointer(regs); 27 29 28 - *callno = syscall_get_nr(target, regs); 29 - if (*callno != -1L && maxargs > 0) 30 - syscall_get_arguments(target, regs, 0, maxargs, args); 30 + info->data.nr = syscall_get_nr(target, regs); 31 + if (info->data.nr != -1L) 32 + syscall_get_arguments(target, regs, 33 + (unsigned long *)&info->data.args[0]); 31 34 32 35 put_task_stack(target); 33 36 return 0; ··· 37 38 /** 38 39 * task_current_syscall - Discover what a blocked task is doing. 39 40 * @target: thread to examine 40 - * @callno: filled with system call number or -1 41 - * @args: filled with @maxargs system call arguments 42 - * @maxargs: number of elements in @args to fill 43 - * @sp: filled with user stack pointer 44 - * @pc: filled with user PC 41 + * @info: structure with the following fields: 42 + * .sp - filled with user stack pointer 43 + * .data.nr - filled with system call number or -1 44 + * .data.args - filled with @maxargs system call arguments 45 + * .data.instruction_pointer - filled with user PC 45 46 * 46 - * If @target is blocked in a system call, returns zero with *@callno 47 - * set to the the call's number and @args filled in with its arguments. 48 - * Registers not used for system call arguments may not be available and 49 - * it is not kosher to use &struct user_regset calls while the system 47 + * If @target is blocked in a system call, returns zero with @info.data.nr 48 + * set to the the call's number and @info.data.args filled in with its 49 + * arguments. Registers not used for system call arguments may not be available 50 + * and it is not kosher to use &struct user_regset calls while the system 50 51 * call is still in progress. Note we may get this result if @target 51 52 * has finished its system call but not yet returned to user mode, such 52 53 * as when it's stopped for signal handling or syscall exit tracing. 53 54 * 54 55 * If @target is blocked in the kernel during a fault or exception, 55 - * returns zero with *@callno set to -1 and does not fill in @args. 56 - * If so, it's now safe to examine @target using &struct user_regset 57 - * get() calls as long as we're sure @target won't return to user mode. 56 + * returns zero with *@info.data.nr set to -1 and does not fill in 57 + * @info.data.args. If so, it's now safe to examine @target using 58 + * &struct user_regset get() calls as long as we're sure @target won't return 59 + * to user mode. 58 60 * 59 61 * Returns -%EAGAIN if @target does not remain blocked. 60 - * 61 - * Returns -%EINVAL if @maxargs is too large (maximum is six). 62 62 */ 63 - int task_current_syscall(struct task_struct *target, long *callno, 64 - unsigned long args[6], unsigned int maxargs, 65 - unsigned long *sp, unsigned long *pc) 63 + int task_current_syscall(struct task_struct *target, struct syscall_info *info) 66 64 { 67 65 long state; 68 66 unsigned long ncsw; 69 67 70 - if (unlikely(maxargs > 6)) 71 - return -EINVAL; 72 - 73 68 if (target == current) 74 - return collect_syscall(target, callno, args, maxargs, sp, pc); 69 + return collect_syscall(target, info); 75 70 76 71 state = target->state; 77 72 if (unlikely(!state)) ··· 73 80 74 81 ncsw = wait_task_inactive(target, state); 75 82 if (unlikely(!ncsw) || 76 - unlikely(collect_syscall(target, callno, args, maxargs, sp, pc)) || 83 + unlikely(collect_syscall(target, info)) || 77 84 unlikely(wait_task_inactive(target, state) != ncsw)) 78 85 return -EAGAIN; 79 86