aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arc/include/asm/syscall.h7
-rw-r--r--arch/arm/include/asm/syscall.h47
-rw-r--r--arch/arm64/include/asm/syscall.h46
-rw-r--r--arch/c6x/include/asm/syscall.h79
-rw-r--r--arch/csky/include/asm/syscall.h26
-rw-r--r--arch/h8300/include/asm/syscall.h34
-rw-r--r--arch/hexagon/include/asm/syscall.h4
-rw-r--r--arch/ia64/include/asm/syscall.h13
-rw-r--r--arch/ia64/kernel/ptrace.c7
-rw-r--r--arch/microblaze/include/asm/syscall.h8
-rw-r--r--arch/mips/include/asm/syscall.h3
-rw-r--r--arch/mips/kernel/ptrace.c2
-rw-r--r--arch/nds32/include/asm/syscall.h62
-rw-r--r--arch/nios2/include/asm/syscall.h84
-rw-r--r--arch/openrisc/include/asm/syscall.h12
-rw-r--r--arch/parisc/include/asm/syscall.h30
-rw-r--r--arch/powerpc/include/asm/syscall.h15
-rw-r--r--arch/riscv/include/asm/syscall.h24
-rw-r--r--arch/s390/include/asm/syscall.h28
-rw-r--r--arch/sh/include/asm/syscall_32.h47
-rw-r--r--arch/sh/include/asm/syscall_64.h8
-rw-r--r--arch/sparc/include/asm/syscall.h11
-rw-r--r--arch/um/include/asm/syscall-generic.h78
-rw-r--r--arch/x86/include/asm/syscall.h142
-rw-r--r--arch/xtensa/include/asm/syscall.h33
-rw-r--r--fs/proc/base.c17
-rw-r--r--include/asm-generic/syscall.h21
-rw-r--r--include/linux/ptrace.h11
-rw-r--r--include/trace/events/syscalls.h2
-rw-r--r--kernel/seccomp.c2
-rw-r--r--kernel/trace/trace_syscalls.c9
-rw-r--r--lib/syscall.c57
32 files changed, 247 insertions, 722 deletions
diff --git a/arch/arc/include/asm/syscall.h b/arch/arc/include/asm/syscall.h
index 29de09804306..c7a4201ed62b 100644
--- a/arch/arc/include/asm/syscall.h
+++ b/arch/arc/include/asm/syscall.h
@@ -55,12 +55,11 @@ syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
55 */ 55 */
56static inline void 56static inline void
57syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, 57syscall_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 unsigned long *inside_ptregs = &(regs->r0); 60 unsigned long *inside_ptregs = &(regs->r0);
61 inside_ptregs -= i; 61 unsigned int n = 6;
62 62 unsigned int i = 0;
63 BUG_ON((i + n) > 6);
64 63
65 while (n--) { 64 while (n--) {
66 args[i++] = (*inside_ptregs); 65 args[i++] = (*inside_ptregs);
diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h
index 06dea6bce293..080ce70cab12 100644
--- a/arch/arm/include/asm/syscall.h
+++ b/arch/arm/include/asm/syscall.h
@@ -55,53 +55,22 @@ static inline void syscall_set_return_value(struct task_struct *task,
55 55
56static inline void syscall_get_arguments(struct task_struct *task, 56static inline void syscall_get_arguments(struct task_struct *task,
57 struct pt_regs *regs, 57 struct pt_regs *regs,
58 unsigned int i, unsigned int n,
59 unsigned long *args) 58 unsigned long *args)
60{ 59{
61 if (n == 0) 60 args[0] = regs->ARM_ORIG_r0;
62 return; 61 args++;
63 62
64 if (i + n > SYSCALL_MAX_ARGS) { 63 memcpy(args, &regs->ARM_r0 + 1, 5 * sizeof(args[0]));
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]));
81} 64}
82 65
83static inline void syscall_set_arguments(struct task_struct *task, 66static inline void syscall_set_arguments(struct task_struct *task,
84 struct pt_regs *regs, 67 struct pt_regs *regs,
85 unsigned int i, unsigned int n,
86 const unsigned long *args) 68 const unsigned long *args)
87{ 69{
88 if (n == 0) 70 regs->ARM_ORIG_r0 = args[0];
89 return; 71 args++;
90 72
91 if (i + n > SYSCALL_MAX_ARGS) { 73 memcpy(&regs->ARM_r0 + 1, args, 5 * sizeof(args[0]));
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]));
105} 74}
106 75
107static inline int syscall_get_arch(void) 76static inline int syscall_get_arch(void)
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index ad8be16a39c9..a179df3674a1 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -65,52 +65,22 @@ static inline void syscall_set_return_value(struct task_struct *task,
65 65
66static inline void syscall_get_arguments(struct task_struct *task, 66static inline void syscall_get_arguments(struct task_struct *task,
67 struct pt_regs *regs, 67 struct pt_regs *regs,
68 unsigned int i, unsigned int n,
69 unsigned long *args) 68 unsigned long *args)
70{ 69{
71 if (n == 0) 70 args[0] = regs->orig_x0;
72 return; 71 args++;
73 72
74 if (i + n > SYSCALL_MAX_ARGS) { 73 memcpy(args, &regs->regs[1], 5 * sizeof(args[0]));
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]));
90} 74}
91 75
92static inline void syscall_set_arguments(struct task_struct *task, 76static inline void syscall_set_arguments(struct task_struct *task,
93 struct pt_regs *regs, 77 struct pt_regs *regs,
94 unsigned int i, unsigned int n,
95 const unsigned long *args) 78 const unsigned long *args)
96{ 79{
97 if (n == 0) 80 regs->orig_x0 = args[0];
98 return; 81 args++;
99 82
100 if (i + n > SYSCALL_MAX_ARGS) { 83 memcpy(&regs->regs[1], args, 5 * sizeof(args[0]));
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]));
114} 84}
115 85
116/* 86/*
diff --git a/arch/c6x/include/asm/syscall.h b/arch/c6x/include/asm/syscall.h
index ae2be315ee9c..15ba8599858e 100644
--- a/arch/c6x/include/asm/syscall.h
+++ b/arch/c6x/include/asm/syscall.h
@@ -46,78 +46,27 @@ static inline void syscall_set_return_value(struct task_struct *task,
46} 46}
47 47
48static inline void syscall_get_arguments(struct task_struct *task, 48static inline void syscall_get_arguments(struct task_struct *task,
49 struct pt_regs *regs, unsigned int i, 49 struct pt_regs *regs,
50 unsigned int n, unsigned long *args) 50 unsigned long *args)
51{ 51{
52 switch (i) { 52 *args++ = regs->a4;
53 case 0: 53 *args++ = regs->b4;
54 if (!n--) 54 *args++ = regs->a6;
55 break; 55 *args++ = regs->b6;
56 *args++ = regs->a4; 56 *args++ = regs->a8;
57 case 1: 57 *args = regs->b8;
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 }
83} 58}
84 59
85static inline void syscall_set_arguments(struct task_struct *task, 60static inline void syscall_set_arguments(struct task_struct *task,
86 struct pt_regs *regs, 61 struct pt_regs *regs,
87 unsigned int i, unsigned int n,
88 const unsigned long *args) 62 const unsigned long *args)
89{ 63{
90 switch (i) { 64 regs->a4 = *args++;
91 case 0: 65 regs->b4 = *args++;
92 if (!n--) 66 regs->a6 = *args++;
93 break; 67 regs->b6 = *args++;
94 regs->a4 = *args++; 68 regs->a8 = *args++;
95 case 1: 69 regs->a9 = *args;
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 }
121} 70}
122 71
123#endif /* __ASM_C6X_SYSCALLS_H */ 72#endif /* __ASM_C6X_SYSCALLS_H */
diff --git a/arch/csky/include/asm/syscall.h b/arch/csky/include/asm/syscall.h
index d637445737b7..bda0a446c63e 100644
--- a/arch/csky/include/asm/syscall.h
+++ b/arch/csky/include/asm/syscall.h
@@ -43,30 +43,20 @@ syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
43 43
44static inline void 44static inline void
45syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, 45syscall_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); 48 args[0] = regs->orig_a0;
49 if (i == 0) { 49 args++;
50 args[0] = regs->orig_a0; 50 memcpy(args, &regs->a1, 5 * sizeof(args[0]));
51 args++;
52 i++;
53 n--;
54 }
55 memcpy(args, &regs->a1 + i * sizeof(regs->a1), n * sizeof(args[0]));
56} 51}
57 52
58static inline void 53static inline void
59syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, 54syscall_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); 57 regs->orig_a0 = args[0];
63 if (i == 0) { 58 args++;
64 regs->orig_a0 = args[0]; 59 memcpy(&regs->a1, args, 5 * sizeof(regs->a1));
65 args++;
66 i++;
67 n--;
68 }
69 memcpy(&regs->a1 + i * sizeof(regs->a1), args, n * sizeof(regs->a0));
70} 60}
71 61
72static inline int 62static inline int
diff --git a/arch/h8300/include/asm/syscall.h b/arch/h8300/include/asm/syscall.h
index 924990401237..ddd483c6ca95 100644
--- a/arch/h8300/include/asm/syscall.h
+++ b/arch/h8300/include/asm/syscall.h
@@ -17,34 +17,14 @@ syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
17 17
18static inline void 18static inline void
19syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, 19syscall_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); 22 *args++ = regs->er1;
23 23 *args++ = regs->er2;
24 while (n > 0) { 24 *args++ = regs->er3;
25 switch (i) { 25 *args++ = regs->er4;
26 case 0: 26 *args++ = regs->er5;
27 *args++ = regs->er1; 27 *args = regs->er6;
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 }
48} 28}
49 29
50 30
diff --git a/arch/hexagon/include/asm/syscall.h b/arch/hexagon/include/asm/syscall.h
index 4af9c7b6f13a..ae3a1e24fabd 100644
--- a/arch/hexagon/include/asm/syscall.h
+++ b/arch/hexagon/include/asm/syscall.h
@@ -37,10 +37,8 @@ static inline long syscall_get_nr(struct task_struct *task,
37 37
38static inline void syscall_get_arguments(struct task_struct *task, 38static inline void syscall_get_arguments(struct task_struct *task,
39 struct pt_regs *regs, 39 struct pt_regs *regs,
40 unsigned int i, unsigned int n,
41 unsigned long *args) 40 unsigned long *args)
42{ 41{
43 BUG_ON(i + n > 6); 42 memcpy(args, &(&regs->r00)[0], 6 * sizeof(args[0]));
44 memcpy(args, &(&regs->r00)[i], n * sizeof(args[0]));
45} 43}
46#endif 44#endif
diff --git a/arch/ia64/include/asm/syscall.h b/arch/ia64/include/asm/syscall.h
index 1d0b875fec44..0d9e7fab4a79 100644
--- a/arch/ia64/include/asm/syscall.h
+++ b/arch/ia64/include/asm/syscall.h
@@ -59,26 +59,19 @@ static inline void syscall_set_return_value(struct task_struct *task,
59} 59}
60 60
61extern void ia64_syscall_get_set_arguments(struct task_struct *task, 61extern void ia64_syscall_get_set_arguments(struct task_struct *task,
62 struct pt_regs *regs, unsigned int i, unsigned int n, 62 struct pt_regs *regs, unsigned long *args, int rw);
63 unsigned long *args, int rw);
64static inline void syscall_get_arguments(struct task_struct *task, 63static inline void syscall_get_arguments(struct task_struct *task,
65 struct pt_regs *regs, 64 struct pt_regs *regs,
66 unsigned int i, unsigned int n,
67 unsigned long *args) 65 unsigned long *args)
68{ 66{
69 BUG_ON(i + n > 6); 67 ia64_syscall_get_set_arguments(task, regs, args, 0);
70
71 ia64_syscall_get_set_arguments(task, regs, i, n, args, 0);
72} 68}
73 69
74static inline void syscall_set_arguments(struct task_struct *task, 70static inline void syscall_set_arguments(struct task_struct *task,
75 struct pt_regs *regs, 71 struct pt_regs *regs,
76 unsigned int i, unsigned int n,
77 unsigned long *args) 72 unsigned long *args)
78{ 73{
79 BUG_ON(i + n > 6); 74 ia64_syscall_get_set_arguments(task, regs, args, 1);
80
81 ia64_syscall_get_set_arguments(task, regs, i, n, args, 1);
82} 75}
83 76
84static inline int syscall_get_arch(void) 77static inline int syscall_get_arch(void)
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 6d50ede0ed69..bf9c24d9ce84 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -2179,12 +2179,11 @@ static void syscall_get_set_args_cb(struct unw_frame_info *info, void *data)
2179} 2179}
2180 2180
2181void ia64_syscall_get_set_arguments(struct task_struct *task, 2181void ia64_syscall_get_set_arguments(struct task_struct *task,
2182 struct pt_regs *regs, unsigned int i, unsigned int n, 2182 struct pt_regs *regs, unsigned long *args, int rw)
2183 unsigned long *args, int rw)
2184{ 2183{
2185 struct syscall_get_set_args data = { 2184 struct syscall_get_set_args data = {
2186 .i = i, 2185 .i = 0,
2187 .n = n, 2186 .n = 6,
2188 .args = args, 2187 .args = args,
2189 .regs = regs, 2188 .regs = regs,
2190 .rw = rw, 2189 .rw = rw,
diff --git a/arch/microblaze/include/asm/syscall.h b/arch/microblaze/include/asm/syscall.h
index 220decd605a4..833d3a53dab3 100644
--- a/arch/microblaze/include/asm/syscall.h
+++ b/arch/microblaze/include/asm/syscall.h
@@ -82,18 +82,22 @@ static inline void microblaze_set_syscall_arg(struct pt_regs *regs,
82 82
83static inline void syscall_get_arguments(struct task_struct *task, 83static inline void syscall_get_arguments(struct task_struct *task,
84 struct pt_regs *regs, 84 struct pt_regs *regs,
85 unsigned int i, unsigned int n,
86 unsigned long *args) 85 unsigned long *args)
87{ 86{
87 unsigned int i = 0;
88 unsigned int n = 6;
89
88 while (n--) 90 while (n--)
89 *args++ = microblaze_get_syscall_arg(regs, i++); 91 *args++ = microblaze_get_syscall_arg(regs, i++);
90} 92}
91 93
92static inline void syscall_set_arguments(struct task_struct *task, 94static inline void syscall_set_arguments(struct task_struct *task,
93 struct pt_regs *regs, 95 struct pt_regs *regs,
94 unsigned int i, unsigned int n,
95 const unsigned long *args) 96 const unsigned long *args)
96{ 97{
98 unsigned int i = 0;
99 unsigned int n = 6;
100
97 while (n--) 101 while (n--)
98 microblaze_set_syscall_arg(regs, i++, *args++); 102 microblaze_set_syscall_arg(regs, i++, *args++);
99} 103}
diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
index 6cf8ffb5367e..a2b4748655df 100644
--- a/arch/mips/include/asm/syscall.h
+++ b/arch/mips/include/asm/syscall.h
@@ -116,9 +116,10 @@ static inline void syscall_set_return_value(struct task_struct *task,
116 116
117static inline void syscall_get_arguments(struct task_struct *task, 117static inline void syscall_get_arguments(struct task_struct *task,
118 struct pt_regs *regs, 118 struct pt_regs *regs,
119 unsigned int i, unsigned int n,
120 unsigned long *args) 119 unsigned long *args)
121{ 120{
121 unsigned int i = 0;
122 unsigned int n = 6;
122 int ret; 123 int ret;
123 124
124 /* O32 ABI syscall() */ 125 /* O32 ABI syscall() */
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 0057c910bc2f..3a62f80958e1 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -1419,7 +1419,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
1419 1419
1420 sd.nr = syscall; 1420 sd.nr = syscall;
1421 sd.arch = syscall_get_arch(); 1421 sd.arch = syscall_get_arch();
1422 syscall_get_arguments(current, regs, 0, 6, args); 1422 syscall_get_arguments(current, regs, args);
1423 for (i = 0; i < 6; i++) 1423 for (i = 0; i < 6; i++)
1424 sd.args[i] = args[i]; 1424 sd.args[i] = args[i];
1425 sd.instruction_pointer = KSTK_EIP(current); 1425 sd.instruction_pointer = KSTK_EIP(current);
diff --git a/arch/nds32/include/asm/syscall.h b/arch/nds32/include/asm/syscall.h
index f7e5e86765fe..671ebd357496 100644
--- a/arch/nds32/include/asm/syscall.h
+++ b/arch/nds32/include/asm/syscall.h
@@ -108,81 +108,41 @@ void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
108 * syscall_get_arguments - extract system call parameter values 108 * syscall_get_arguments - extract system call parameter values
109 * @task: task of interest, must be blocked 109 * @task: task of interest, must be blocked
110 * @regs: task_pt_regs() of @task 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 * @args: array filled with argument values 111 * @args: array filled with argument values
114 * 112 *
115 * Fetches @n arguments to the system call starting with the @i'th argument 113 * Fetches 6 arguments to the system call (from 0 through 5). The first
116 * (from 0 through 5). Argument @i is stored in @args[0], and so on. 114 * argument is stored in @args[0], and so on.
117 * An arch inline version is probably optimal when @i and @n are constants.
118 * 115 *
119 * It's only valid to call this when @task is stopped for tracing on 116 * It's only valid to call this when @task is stopped for tracing on
120 * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 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#define SYSCALL_MAX_ARGS 6 119#define SYSCALL_MAX_ARGS 6
125void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, 120void 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) 123 args[0] = regs->orig_r0;
129 return; 124 args++;
130 if (i + n > SYSCALL_MAX_ARGS) { 125 memcpy(args, &regs->uregs[0] + 1, 5 * sizeof(args[0]));
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]));
147} 126}
148 127
149/** 128/**
150 * syscall_set_arguments - change system call parameter value 129 * syscall_set_arguments - change system call parameter value
151 * @task: task of interest, must be in system call entry tracing 130 * @task: task of interest, must be in system call entry tracing
152 * @regs: task_pt_regs() of @task 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 * @args: array of argument values to store 132 * @args: array of argument values to store
156 * 133 *
157 * Changes @n arguments to the system call starting with the @i'th argument. 134 * Changes 6 arguments to the system call. The first argument gets value
158 * Argument @i gets value @args[0], and so on. 135 * @args[0], and so on.
159 * An arch inline version is probably optimal when @i and @n are constants.
160 * 136 *
161 * It's only valid to call this when @task is stopped for tracing on 137 * It's only valid to call this when @task is stopped for tracing on
162 * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 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 */
166void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, 140void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
167 unsigned int i, unsigned int n,
168 const unsigned long *args) 141 const unsigned long *args)
169{ 142{
170 if (n == 0) 143 regs->orig_r0 = args[0];
171 return; 144 args++;
172
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 145
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#endif /* _ASM_NDS32_SYSCALL_H */ 148#endif /* _ASM_NDS32_SYSCALL_H */
diff --git a/arch/nios2/include/asm/syscall.h b/arch/nios2/include/asm/syscall.h
index 9de220854c4a..d7624ed06efb 100644
--- a/arch/nios2/include/asm/syscall.h
+++ b/arch/nios2/include/asm/syscall.h
@@ -58,81 +58,25 @@ static inline void syscall_set_return_value(struct task_struct *task,
58} 58}
59 59
60static inline void syscall_get_arguments(struct task_struct *task, 60static inline void syscall_get_arguments(struct task_struct *task,
61 struct pt_regs *regs, unsigned int i, unsigned int n, 61 struct pt_regs *regs, unsigned long *args)
62 unsigned long *args)
63{ 62{
64 BUG_ON(i + n > 6); 63 *args++ = regs->r4;
65 64 *args++ = regs->r5;
66 switch (i) { 65 *args++ = regs->r6;
67 case 0: 66 *args++ = regs->r7;
68 if (!n--) 67 *args++ = regs->r8;
69 break; 68 *args = regs->r9;
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 }
97} 69}
98 70
99static inline void syscall_set_arguments(struct task_struct *task, 71static inline void syscall_set_arguments(struct task_struct *task,
100 struct pt_regs *regs, unsigned int i, unsigned int n, 72 struct pt_regs *regs, const unsigned long *args)
101 const unsigned long *args)
102{ 73{
103 BUG_ON(i + n > 6); 74 regs->r4 = *args++;
104 75 regs->r5 = *args++;
105 switch (i) { 76 regs->r6 = *args++;
106 case 0: 77 regs->r7 = *args++;
107 if (!n--) 78 regs->r8 = *args++;
108 break; 79 regs->r9 = *args;
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 }
136} 80}
137 81
138#endif 82#endif
diff --git a/arch/openrisc/include/asm/syscall.h b/arch/openrisc/include/asm/syscall.h
index 2db9f1cf0694..b4ff07c1baed 100644
--- a/arch/openrisc/include/asm/syscall.h
+++ b/arch/openrisc/include/asm/syscall.h
@@ -56,20 +56,16 @@ syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
56 56
57static inline void 57static inline void
58syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, 58syscall_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); 61 memcpy(args, &regs->gpr[3], 6 * sizeof(args[0]));
62
63 memcpy(args, &regs->gpr[3 + i], n * sizeof(args[0]));
64} 62}
65 63
66static inline void 64static inline void
67syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, 65syscall_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); 68 memcpy(&regs->gpr[3], args, 6 * sizeof(args[0]));
71
72 memcpy(&regs->gpr[3 + i], args, n * sizeof(args[0]));
73} 69}
74 70
75static inline int syscall_get_arch(void) 71static inline int syscall_get_arch(void)
diff --git a/arch/parisc/include/asm/syscall.h b/arch/parisc/include/asm/syscall.h
index 8bff1a58c97f..62a6d477fae0 100644
--- a/arch/parisc/include/asm/syscall.h
+++ b/arch/parisc/include/asm/syscall.h
@@ -18,29 +18,15 @@ static inline long syscall_get_nr(struct task_struct *tsk,
18} 18}
19 19
20static inline void syscall_get_arguments(struct task_struct *tsk, 20static inline void syscall_get_arguments(struct task_struct *tsk,
21 struct pt_regs *regs, unsigned int i, 21 struct pt_regs *regs,
22 unsigned int n, unsigned long *args) 22 unsigned long *args)
23{ 23{
24 BUG_ON(i); 24 args[5] = regs->gr[21];
25 25 args[4] = regs->gr[22];
26 switch (n) { 26 args[3] = regs->gr[23];
27 case 6: 27 args[2] = regs->gr[24];
28 args[5] = regs->gr[21]; 28 args[1] = regs->gr[25];
29 case 5: 29 args[0] = regs->gr[26];
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 }
44} 30}
45 31
46static inline long syscall_get_return_value(struct task_struct *task, 32static inline long syscall_get_return_value(struct task_struct *task,
diff --git a/arch/powerpc/include/asm/syscall.h b/arch/powerpc/include/asm/syscall.h
index 1a0e7a8b1c81..1243045bad2d 100644
--- a/arch/powerpc/include/asm/syscall.h
+++ b/arch/powerpc/include/asm/syscall.h
@@ -65,22 +65,20 @@ static inline void syscall_set_return_value(struct task_struct *task,
65 65
66static inline void syscall_get_arguments(struct task_struct *task, 66static inline void syscall_get_arguments(struct task_struct *task,
67 struct pt_regs *regs, 67 struct pt_regs *regs,
68 unsigned int i, unsigned int n,
69 unsigned long *args) 68 unsigned long *args)
70{ 69{
71 unsigned long val, mask = -1UL; 70 unsigned long val, mask = -1UL;
72 71 unsigned int n = 6;
73 BUG_ON(i + n > 6);
74 72
75#ifdef CONFIG_COMPAT 73#ifdef CONFIG_COMPAT
76 if (test_tsk_thread_flag(task, TIF_32BIT)) 74 if (test_tsk_thread_flag(task, TIF_32BIT))
77 mask = 0xffffffff; 75 mask = 0xffffffff;
78#endif 76#endif
79 while (n--) { 77 while (n--) {
80 if (n == 0 && i == 0) 78 if (n == 0)
81 val = regs->orig_gpr3; 79 val = regs->orig_gpr3;
82 else 80 else
83 val = regs->gpr[3 + i + n]; 81 val = regs->gpr[3 + n];
84 82
85 args[n] = val & mask; 83 args[n] = val & mask;
86 } 84 }
@@ -88,15 +86,12 @@ static inline void syscall_get_arguments(struct task_struct *task,
88 86
89static inline void syscall_set_arguments(struct task_struct *task, 87static inline void syscall_set_arguments(struct task_struct *task,
90 struct pt_regs *regs, 88 struct pt_regs *regs,
91 unsigned int i, unsigned int n,
92 const unsigned long *args) 89 const unsigned long *args)
93{ 90{
94 BUG_ON(i + n > 6); 91 memcpy(&regs->gpr[3], args, 6 * sizeof(args[0]));
95 memcpy(&regs->gpr[3 + i], args, n * sizeof(args[0]));
96 92
97 /* Also copy the first argument into orig_gpr3 */ 93 /* Also copy the first argument into orig_gpr3 */
98 if (i == 0 && n > 0) 94 regs->orig_gpr3 = args[0];
99 regs->orig_gpr3 = args[0];
100} 95}
101 96
102static inline int syscall_get_arch(void) 97static inline int syscall_get_arch(void)
diff --git a/arch/riscv/include/asm/syscall.h b/arch/riscv/include/asm/syscall.h
index bba3da6ef157..a3d5273ded7c 100644
--- a/arch/riscv/include/asm/syscall.h
+++ b/arch/riscv/include/asm/syscall.h
@@ -72,32 +72,20 @@ static inline void syscall_set_return_value(struct task_struct *task,
72 72
73static inline void syscall_get_arguments(struct task_struct *task, 73static inline void syscall_get_arguments(struct task_struct *task,
74 struct pt_regs *regs, 74 struct pt_regs *regs,
75 unsigned int i, unsigned int n,
76 unsigned long *args) 75 unsigned long *args)
77{ 76{
78 BUG_ON(i + n > 6); 77 args[0] = regs->orig_a0;
79 if (i == 0) { 78 args++;
80 args[0] = regs->orig_a0; 79 memcpy(args, &regs->a1, 5 * sizeof(args[0]));
81 args++;
82 i++;
83 n--;
84 }
85 memcpy(args, &regs->a1 + i * sizeof(regs->a1), n * sizeof(args[0]));
86} 80}
87 81
88static inline void syscall_set_arguments(struct task_struct *task, 82static inline void syscall_set_arguments(struct task_struct *task,
89 struct pt_regs *regs, 83 struct pt_regs *regs,
90 unsigned int i, unsigned int n,
91 const unsigned long *args) 84 const unsigned long *args)
92{ 85{
93 BUG_ON(i + n > 6); 86 regs->orig_a0 = args[0];
94 if (i == 0) { 87 args++;
95 regs->orig_a0 = args[0]; 88 memcpy(&regs->a1, args, 5 * sizeof(regs->a1));
96 args++;
97 i++;
98 n--;
99 }
100 memcpy(&regs->a1 + i * sizeof(regs->a1), args, n * sizeof(regs->a0));
101} 89}
102 90
103static inline int syscall_get_arch(void) 91static inline int syscall_get_arch(void)
diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h
index 96f9a9151fde..59c3e91f2cdb 100644
--- a/arch/s390/include/asm/syscall.h
+++ b/arch/s390/include/asm/syscall.h
@@ -56,40 +56,32 @@ static inline void syscall_set_return_value(struct task_struct *task,
56 56
57static inline void syscall_get_arguments(struct task_struct *task, 57static inline void syscall_get_arguments(struct task_struct *task,
58 struct pt_regs *regs, 58 struct pt_regs *regs,
59 unsigned int i, unsigned int n,
60 unsigned long *args) 59 unsigned long *args)
61{ 60{
62 unsigned long mask = -1UL; 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#ifdef CONFIG_COMPAT 64#ifdef CONFIG_COMPAT
72 if (test_tsk_thread_flag(task, TIF_31BIT)) 65 if (test_tsk_thread_flag(task, TIF_31BIT))
73 mask = 0xffffffff; 66 mask = 0xffffffff;
74#endif 67#endif
75 while (n-- > 0) 68 while (n-- > 0)
76 if (i + n > 0) 69 if (n > 0)
77 args[n] = regs->gprs[2 + i + n] & mask; 70 args[n] = regs->gprs[2 + n] & mask;
78 if (i == 0) 71
79 args[0] = regs->orig_gpr2 & mask; 72 args[0] = regs->orig_gpr2 & mask;
80} 73}
81 74
82static inline void syscall_set_arguments(struct task_struct *task, 75static inline void syscall_set_arguments(struct task_struct *task,
83 struct pt_regs *regs, 76 struct pt_regs *regs,
84 unsigned int i, unsigned int n,
85 const unsigned long *args) 77 const unsigned long *args)
86{ 78{
87 BUG_ON(i + n > 6); 79 unsigned int n = 6;
80
88 while (n-- > 0) 81 while (n-- > 0)
89 if (i + n > 0) 82 if (n > 0)
90 regs->gprs[2 + i + n] = args[n]; 83 regs->gprs[2 + n] = args[n];
91 if (i == 0) 84 regs->orig_gpr2 = args[0];
92 regs->orig_gpr2 = args[0];
93} 85}
94 86
95static inline int syscall_get_arch(void) 87static inline int syscall_get_arch(void)
diff --git a/arch/sh/include/asm/syscall_32.h b/arch/sh/include/asm/syscall_32.h
index 6e118799831c..8c9d7e5e5dcc 100644
--- a/arch/sh/include/asm/syscall_32.h
+++ b/arch/sh/include/asm/syscall_32.h
@@ -48,51 +48,28 @@ static inline void syscall_set_return_value(struct task_struct *task,
48 48
49static inline void syscall_get_arguments(struct task_struct *task, 49static inline void syscall_get_arguments(struct task_struct *task,
50 struct pt_regs *regs, 50 struct pt_regs *regs,
51 unsigned int i, unsigned int n,
52 unsigned long *args) 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 /* Argument pattern is: R4, R5, R6, R7, R0, R1 */ 54 /* Argument pattern is: R4, R5, R6, R7, R0, R1 */
63 switch (n) { 55 args[5] = regs->regs[1];
64 case 6: args[5] = regs->regs[1]; 56 args[4] = regs->regs[0];
65 case 5: args[4] = regs->regs[0]; 57 args[3] = regs->regs[7];
66 case 4: args[3] = regs->regs[7]; 58 args[2] = regs->regs[6];
67 case 3: args[2] = regs->regs[6]; 59 args[1] = regs->regs[5];
68 case 2: args[1] = regs->regs[5]; 60 args[0] = regs->regs[4];
69 case 1: args[0] = regs->regs[4];
70 case 0:
71 break;
72 default:
73 BUG();
74 }
75} 61}
76 62
77static inline void syscall_set_arguments(struct task_struct *task, 63static inline void syscall_set_arguments(struct task_struct *task,
78 struct pt_regs *regs, 64 struct pt_regs *regs,
79 unsigned int i, unsigned int n,
80 const unsigned long *args) 65 const unsigned long *args)
81{ 66{
82 /* Same note as above applies */ 67 regs->regs[1] = args[5];
83 BUG_ON(i); 68 regs->regs[0] = args[4];
84 69 regs->regs[7] = args[3];
85 switch (n) { 70 regs->regs[6] = args[2];
86 case 6: regs->regs[1] = args[5]; 71 regs->regs[5] = args[1];
87 case 5: regs->regs[0] = args[4]; 72 regs->regs[4] = args[0];
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 }
96} 73}
97 74
98static inline int syscall_get_arch(void) 75static inline int syscall_get_arch(void)
diff --git a/arch/sh/include/asm/syscall_64.h b/arch/sh/include/asm/syscall_64.h
index 43882580c7f9..22fad97da066 100644
--- a/arch/sh/include/asm/syscall_64.h
+++ b/arch/sh/include/asm/syscall_64.h
@@ -47,20 +47,16 @@ static inline void syscall_set_return_value(struct task_struct *task,
47 47
48static inline void syscall_get_arguments(struct task_struct *task, 48static inline void syscall_get_arguments(struct task_struct *task,
49 struct pt_regs *regs, 49 struct pt_regs *regs,
50 unsigned int i, unsigned int n,
51 unsigned long *args) 50 unsigned long *args)
52{ 51{
53 BUG_ON(i + n > 6); 52 memcpy(args, &regs->regs[2], 6 * sizeof(args[0]));
54 memcpy(args, &regs->regs[2 + i], n * sizeof(args[0]));
55} 53}
56 54
57static inline void syscall_set_arguments(struct task_struct *task, 55static inline void syscall_set_arguments(struct task_struct *task,
58 struct pt_regs *regs, 56 struct pt_regs *regs,
59 unsigned int i, unsigned int n,
60 const unsigned long *args) 57 const unsigned long *args)
61{ 58{
62 BUG_ON(i + n > 6); 59 memcpy(&regs->regs[2], args, 6 * sizeof(args[0]));
63 memcpy(&regs->regs[2 + i], args, n * sizeof(args[0]));
64} 60}
65 61
66static inline int syscall_get_arch(void) 62static inline int syscall_get_arch(void)
diff --git a/arch/sparc/include/asm/syscall.h b/arch/sparc/include/asm/syscall.h
index 053989e3f6a6..4d075434e816 100644
--- a/arch/sparc/include/asm/syscall.h
+++ b/arch/sparc/include/asm/syscall.h
@@ -96,11 +96,11 @@ static inline void syscall_set_return_value(struct task_struct *task,
96 96
97static inline void syscall_get_arguments(struct task_struct *task, 97static inline void syscall_get_arguments(struct task_struct *task,
98 struct pt_regs *regs, 98 struct pt_regs *regs,
99 unsigned int i, unsigned int n,
100 unsigned long *args) 99 unsigned long *args)
101{ 100{
102 int zero_extend = 0; 101 int zero_extend = 0;
103 unsigned int j; 102 unsigned int j;
103 unsigned int n = 6;
104 104
105#ifdef CONFIG_SPARC64 105#ifdef CONFIG_SPARC64
106 if (test_tsk_thread_flag(task, TIF_32BIT)) 106 if (test_tsk_thread_flag(task, TIF_32BIT))
@@ -108,7 +108,7 @@ static inline void syscall_get_arguments(struct task_struct *task,
108#endif 108#endif
109 109
110 for (j = 0; j < n; j++) { 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 if (zero_extend) 113 if (zero_extend)
114 args[j] = (u32) val; 114 args[j] = (u32) val;
@@ -119,13 +119,12 @@ static inline void syscall_get_arguments(struct task_struct *task,
119 119
120static inline void syscall_set_arguments(struct task_struct *task, 120static inline void syscall_set_arguments(struct task_struct *task,
121 struct pt_regs *regs, 121 struct pt_regs *regs,
122 unsigned int i, unsigned int n,
123 const unsigned long *args) 122 const unsigned long *args)
124{ 123{
125 unsigned int j; 124 unsigned int i;
126 125
127 for (j = 0; j < n; j++) 126 for (i = 0; i < 6; i++)
128 regs->u_regs[UREG_I0 + i + j] = args[j]; 127 regs->u_regs[UREG_I0 + i] = args[i];
129} 128}
130 129
131static inline int syscall_get_arch(void) 130static inline int syscall_get_arch(void)
diff --git a/arch/um/include/asm/syscall-generic.h b/arch/um/include/asm/syscall-generic.h
index 9fb9cf8cd39a..98e50c50c12e 100644
--- a/arch/um/include/asm/syscall-generic.h
+++ b/arch/um/include/asm/syscall-generic.h
@@ -53,84 +53,30 @@ static inline void syscall_set_return_value(struct task_struct *task,
53 53
54static inline void syscall_get_arguments(struct task_struct *task, 54static inline void syscall_get_arguments(struct task_struct *task,
55 struct pt_regs *regs, 55 struct pt_regs *regs,
56 unsigned int i, unsigned int n,
57 unsigned long *args) 56 unsigned long *args)
58{ 57{
59 const struct uml_pt_regs *r = &regs->regs; 58 const struct uml_pt_regs *r = &regs->regs;
60 59
61 switch (i) { 60 *args++ = UPT_SYSCALL_ARG1(r);
62 case 0: 61 *args++ = UPT_SYSCALL_ARG2(r);
63 if (!n--) 62 *args++ = UPT_SYSCALL_ARG3(r);
64 break; 63 *args++ = UPT_SYSCALL_ARG4(r);
65 *args++ = UPT_SYSCALL_ARG1(r); 64 *args++ = UPT_SYSCALL_ARG5(r);
66 case 1: 65 *args = UPT_SYSCALL_ARG6(r);
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} 66}
94 67
95static inline void syscall_set_arguments(struct task_struct *task, 68static inline void syscall_set_arguments(struct task_struct *task,
96 struct pt_regs *regs, 69 struct pt_regs *regs,
97 unsigned int i, unsigned int n,
98 const unsigned long *args) 70 const unsigned long *args)
99{ 71{
100 struct uml_pt_regs *r = &regs->regs; 72 struct uml_pt_regs *r = &regs->regs;
101 73
102 switch (i) { 74 UPT_SYSCALL_ARG1(r) = *args++;
103 case 0: 75 UPT_SYSCALL_ARG2(r) = *args++;
104 if (!n--) 76 UPT_SYSCALL_ARG3(r) = *args++;
105 break; 77 UPT_SYSCALL_ARG4(r) = *args++;
106 UPT_SYSCALL_ARG1(r) = *args++; 78 UPT_SYSCALL_ARG5(r) = *args++;
107 case 1: 79 UPT_SYSCALL_ARG6(r) = *args;
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} 80}
135 81
136/* See arch/x86/um/asm/syscall.h for syscall_get_arch() definition. */ 82/* See arch/x86/um/asm/syscall.h for syscall_get_arch() definition. */
diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h
index d653139857af..4c305471ec33 100644
--- a/arch/x86/include/asm/syscall.h
+++ b/arch/x86/include/asm/syscall.h
@@ -91,11 +91,9 @@ static inline void syscall_set_return_value(struct task_struct *task,
91 91
92static inline void syscall_get_arguments(struct task_struct *task, 92static inline void syscall_get_arguments(struct task_struct *task,
93 struct pt_regs *regs, 93 struct pt_regs *regs,
94 unsigned int i, unsigned int n,
95 unsigned long *args) 94 unsigned long *args)
96{ 95{
97 BUG_ON(i + n > 6); 96 memcpy(args, &regs->bx, 6 * sizeof(args[0]));
98 memcpy(args, &regs->bx + i, n * sizeof(args[0]));
99} 97}
100 98
101static inline void syscall_set_arguments(struct task_struct *task, 99static inline void syscall_set_arguments(struct task_struct *task,
@@ -116,124 +114,50 @@ static inline int syscall_get_arch(void)
116 114
117static inline void syscall_get_arguments(struct task_struct *task, 115static inline void syscall_get_arguments(struct task_struct *task,
118 struct pt_regs *regs, 116 struct pt_regs *regs,
119 unsigned int i, unsigned int n,
120 unsigned long *args) 117 unsigned long *args)
121{ 118{
122# ifdef CONFIG_IA32_EMULATION 119# ifdef CONFIG_IA32_EMULATION
123 if (task->thread_info.status & TS_COMPAT) 120 if (task->thread_info.status & TS_COMPAT) {
124 switch (i) { 121 *args++ = regs->bx;
125 case 0: 122 *args++ = regs->cx;
126 if (!n--) break; 123 *args++ = regs->dx;
127 *args++ = regs->bx; 124 *args++ = regs->si;
128 case 1: 125 *args++ = regs->di;
129 if (!n--) break; 126 *args = regs->bp;
130 *args++ = regs->cx; 127 } else
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
150# endif 128# endif
151 switch (i) { 129 {
152 case 0: 130 *args++ = regs->di;
153 if (!n--) break; 131 *args++ = regs->si;
154 *args++ = regs->di; 132 *args++ = regs->dx;
155 case 1: 133 *args++ = regs->r10;
156 if (!n--) break; 134 *args++ = regs->r8;
157 *args++ = regs->si; 135 *args = regs->r9;
158 case 2: 136 }
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 }
176} 137}
177 138
178static inline void syscall_set_arguments(struct task_struct *task, 139static inline void syscall_set_arguments(struct task_struct *task,
179 struct pt_regs *regs, 140 struct pt_regs *regs,
180 unsigned int i, unsigned int n,
181 const unsigned long *args) 141 const unsigned long *args)
182{ 142{
183# ifdef CONFIG_IA32_EMULATION 143# ifdef CONFIG_IA32_EMULATION
184 if (task->thread_info.status & TS_COMPAT) 144 if (task->thread_info.status & TS_COMPAT) {
185 switch (i) { 145 regs->bx = *args++;
186 case 0: 146 regs->cx = *args++;
187 if (!n--) break; 147 regs->dx = *args++;
188 regs->bx = *args++; 148 regs->si = *args++;
189 case 1: 149 regs->di = *args++;
190 if (!n--) break; 150 regs->bp = *args;
191 regs->cx = *args++; 151 } else
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
211# endif 152# endif
212 switch (i) { 153 {
213 case 0: 154 regs->di = *args++;
214 if (!n--) break; 155 regs->si = *args++;
215 regs->di = *args++; 156 regs->dx = *args++;
216 case 1: 157 regs->r10 = *args++;
217 if (!n--) break; 158 regs->r8 = *args++;
218 regs->si = *args++; 159 regs->r9 = *args;
219 case 2: 160 }
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 }
237} 161}
238 162
239static inline int syscall_get_arch(void) 163static inline int syscall_get_arch(void)
diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h
index a168bf81c7f4..91dc06d58060 100644
--- a/arch/xtensa/include/asm/syscall.h
+++ b/arch/xtensa/include/asm/syscall.h
@@ -59,45 +59,24 @@ static inline void syscall_set_return_value(struct task_struct *task,
59 59
60static inline void syscall_get_arguments(struct task_struct *task, 60static inline void syscall_get_arguments(struct task_struct *task,
61 struct pt_regs *regs, 61 struct pt_regs *regs,
62 unsigned int i, unsigned int n,
63 unsigned long *args) 62 unsigned long *args)
64{ 63{
65 static const unsigned int reg[] = XTENSA_SYSCALL_ARGUMENT_REGS; 64 static const unsigned int reg[] = XTENSA_SYSCALL_ARGUMENT_REGS;
66 unsigned int j; 65 unsigned int i;
67 66
68 if (n == 0) 67 for (i = 0; i < 6; ++i)
69 return; 68 args[i] = regs->areg[reg[i]];
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 }
79} 69}
80 70
81static inline void syscall_set_arguments(struct task_struct *task, 71static inline void syscall_set_arguments(struct task_struct *task,
82 struct pt_regs *regs, 72 struct pt_regs *regs,
83 unsigned int i, unsigned int n,
84 const unsigned long *args) 73 const unsigned long *args)
85{ 74{
86 static const unsigned int reg[] = XTENSA_SYSCALL_ARGUMENT_REGS; 75 static const unsigned int reg[] = XTENSA_SYSCALL_ARGUMENT_REGS;
87 unsigned int j; 76 unsigned int i;
88
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 77
99 for (j = 0; j < n; ++j) 78 for (i = 0; i < 6; ++i)
100 regs->areg[reg[i + j]] = args[j]; 79 regs->areg[reg[i]] = args[i];
101} 80}
102 81
103asmlinkage long xtensa_rt_sigreturn(struct pt_regs*); 82asmlinkage long xtensa_rt_sigreturn(struct pt_regs*);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index ddef482f1334..6a803a0b75df 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -616,24 +616,25 @@ static int proc_pid_limits(struct seq_file *m, struct pid_namespace *ns,
616static int proc_pid_syscall(struct seq_file *m, struct pid_namespace *ns, 616static int proc_pid_syscall(struct seq_file *m, struct pid_namespace *ns,
617 struct pid *pid, struct task_struct *task) 617 struct pid *pid, struct task_struct *task)
618{ 618{
619 long nr; 619 struct syscall_info info;
620 unsigned long args[6], sp, pc; 620 u64 *args = &info.data.args[0];
621 int res; 621 int res;
622 622
623 res = lock_trace(task); 623 res = lock_trace(task);
624 if (res) 624 if (res)
625 return res; 625 return res;
626 626
627 if (task_current_syscall(task, &nr, args, 6, &sp, &pc)) 627 if (task_current_syscall(task, &info))
628 seq_puts(m, "running\n"); 628 seq_puts(m, "running\n");
629 else if (nr < 0) 629 else if (info.data.nr < 0)
630 seq_printf(m, "%ld 0x%lx 0x%lx\n", nr, sp, pc); 630 seq_printf(m, "%d 0x%llx 0x%llx\n",
631 info.data.nr, info.sp, info.data.instruction_pointer);
631 else 632 else
632 seq_printf(m, 633 seq_printf(m,
633 "%ld 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", 634 "%d 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx\n",
634 nr, 635 info.data.nr,
635 args[0], args[1], args[2], args[3], args[4], args[5], 636 args[0], args[1], args[2], args[3], args[4], args[5],
636 sp, pc); 637 info.sp, info.data.instruction_pointer);
637 unlock_trace(task); 638 unlock_trace(task);
638 639
639 return 0; 640 return 0;
diff --git a/include/asm-generic/syscall.h b/include/asm-generic/syscall.h
index 0c938a4354f6..b88239e9efe4 100644
--- a/include/asm-generic/syscall.h
+++ b/include/asm-generic/syscall.h
@@ -105,41 +105,30 @@ void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
105 * syscall_get_arguments - extract system call parameter values 105 * syscall_get_arguments - extract system call parameter values
106 * @task: task of interest, must be blocked 106 * @task: task of interest, must be blocked
107 * @regs: task_pt_regs() of @task 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 * @args: array filled with argument values 108 * @args: array filled with argument values
111 * 109 *
112 * Fetches @n arguments to the system call starting with the @i'th argument 110 * Fetches 6 arguments to the system call. First argument is stored in
113 * (from 0 through 5). Argument @i is stored in @args[0], and so on. 111* @args[0], and so on.
114 * An arch inline version is probably optimal when @i and @n are constants.
115 * 112 *
116 * It's only valid to call this when @task is stopped for tracing on 113 * It's only valid to call this when @task is stopped for tracing on
117 * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 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 */
121void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, 116void 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 * syscall_set_arguments - change system call parameter value 120 * syscall_set_arguments - change system call parameter value
126 * @task: task of interest, must be in system call entry tracing 121 * @task: task of interest, must be in system call entry tracing
127 * @regs: task_pt_regs() of @task 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 * @args: array of argument values to store 123 * @args: array of argument values to store
131 * 124 *
132 * Changes @n arguments to the system call starting with the @i'th argument. 125 * Changes 6 arguments to the system call.
133 * Argument @i gets value @args[0], and so on. 126 * The first argument gets value @args[0], and so on.
134 * An arch inline version is probably optimal when @i and @n are constants.
135 * 127 *
136 * It's only valid to call this when @task is stopped for tracing on 128 * It's only valid to call this when @task is stopped for tracing on
137 * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT. 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 */
141void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, 131void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
142 unsigned int i, unsigned int n,
143 const unsigned long *args); 132 const unsigned long *args);
144 133
145/** 134/**
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index edb9b040c94c..d5084ebd9f03 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -9,6 +9,13 @@
9#include <linux/bug.h> /* For BUG_ON. */ 9#include <linux/bug.h> /* For BUG_ON. */
10#include <linux/pid_namespace.h> /* For task_active_pid_ns. */ 10#include <linux/pid_namespace.h> /* For task_active_pid_ns. */
11#include <uapi/linux/ptrace.h> 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 */
15struct syscall_info {
16 __u64 sp;
17 struct seccomp_data data;
18};
12 19
13extern int ptrace_access_vm(struct task_struct *tsk, unsigned long addr, 20extern int ptrace_access_vm(struct task_struct *tsk, unsigned long addr,
14 void *buf, int len, unsigned int gup_flags); 21 void *buf, int len, unsigned int gup_flags);
@@ -407,9 +414,7 @@ static inline void user_single_step_report(struct pt_regs *regs)
407#define current_user_stack_pointer() user_stack_pointer(current_pt_regs()) 414#define current_user_stack_pointer() user_stack_pointer(current_pt_regs())
408#endif 415#endif
409 416
410extern int task_current_syscall(struct task_struct *target, long *callno, 417extern int task_current_syscall(struct task_struct *target, struct syscall_info *info);
411 unsigned long args[6], unsigned int maxargs,
412 unsigned long *sp, unsigned long *pc);
413 418
414extern void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact); 419extern void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact);
415#endif 420#endif
diff --git a/include/trace/events/syscalls.h b/include/trace/events/syscalls.h
index 44a3259ed4a5..b6e0cbc2c71f 100644
--- a/include/trace/events/syscalls.h
+++ b/include/trace/events/syscalls.h
@@ -28,7 +28,7 @@ TRACE_EVENT_FN(sys_enter,
28 28
29 TP_fast_assign( 29 TP_fast_assign(
30 __entry->id = id; 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 TP_printk("NR %ld (%lx, %lx, %lx, %lx, %lx, %lx)", 34 TP_printk("NR %ld (%lx, %lx, %lx, %lx, %lx, %lx)",
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 54a0347ca812..df27e499956a 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -149,7 +149,7 @@ static void populate_seccomp_data(struct seccomp_data *sd)
149 149
150 sd->nr = syscall_get_nr(task, regs); 150 sd->nr = syscall_get_nr(task, regs);
151 sd->arch = syscall_get_arch(); 151 sd->arch = syscall_get_arch();
152 syscall_get_arguments(task, regs, 0, 6, args); 152 syscall_get_arguments(task, regs, args);
153 sd->args[0] = args[0]; 153 sd->args[0] = args[0];
154 sd->args[1] = args[1]; 154 sd->args[1] = args[1];
155 sd->args[2] = args[2]; 155 sd->args[2] = args[2];
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index f93a56d2db27..fa8fbff736d6 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -314,6 +314,7 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id)
314 struct ring_buffer_event *event; 314 struct ring_buffer_event *event;
315 struct ring_buffer *buffer; 315 struct ring_buffer *buffer;
316 unsigned long irq_flags; 316 unsigned long irq_flags;
317 unsigned long args[6];
317 int pc; 318 int pc;
318 int syscall_nr; 319 int syscall_nr;
319 int size; 320 int size;
@@ -347,7 +348,8 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id)
347 348
348 entry = ring_buffer_event_data(event); 349 entry = ring_buffer_event_data(event);
349 entry->nr = syscall_nr; 350 entry->nr = syscall_nr;
350 syscall_get_arguments(current, regs, 0, sys_data->nb_args, entry->args); 351 syscall_get_arguments(current, regs, args);
352 memcpy(entry->args, args, sizeof(unsigned long) * sys_data->nb_args);
351 353
352 event_trigger_unlock_commit(trace_file, buffer, event, entry, 354 event_trigger_unlock_commit(trace_file, buffer, event, entry,
353 irq_flags, pc); 355 irq_flags, pc);
@@ -583,6 +585,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id)
583 struct syscall_metadata *sys_data; 585 struct syscall_metadata *sys_data;
584 struct syscall_trace_enter *rec; 586 struct syscall_trace_enter *rec;
585 struct hlist_head *head; 587 struct hlist_head *head;
588 unsigned long args[6];
586 bool valid_prog_array; 589 bool valid_prog_array;
587 int syscall_nr; 590 int syscall_nr;
588 int rctx; 591 int rctx;
@@ -613,8 +616,8 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id)
613 return; 616 return;
614 617
615 rec->nr = syscall_nr; 618 rec->nr = syscall_nr;
616 syscall_get_arguments(current, regs, 0, sys_data->nb_args, 619 syscall_get_arguments(current, regs, args);
617 (unsigned long *)&rec->args); 620 memcpy(&rec->args, args, sizeof(unsigned long) * sys_data->nb_args);
618 621
619 if ((valid_prog_array && 622 if ((valid_prog_array &&
620 !perf_call_bpf_enter(sys_data->enter_event, regs, sys_data, rec)) || 623 !perf_call_bpf_enter(sys_data->enter_event, regs, sys_data, rec)) ||
diff --git a/lib/syscall.c b/lib/syscall.c
index 1a7077f20eae..fb328e7ccb08 100644
--- a/lib/syscall.c
+++ b/lib/syscall.c
@@ -5,16 +5,14 @@
5#include <linux/export.h> 5#include <linux/export.h>
6#include <asm/syscall.h> 6#include <asm/syscall.h>
7 7
8static int collect_syscall(struct task_struct *target, long *callno, 8static int collect_syscall(struct task_struct *target, struct syscall_info *info)
9 unsigned long args[6], unsigned int maxargs,
10 unsigned long *sp, unsigned long *pc)
11{ 9{
12 struct pt_regs *regs; 10 struct pt_regs *regs;
13 11
14 if (!try_get_task_stack(target)) { 12 if (!try_get_task_stack(target)) {
15 /* Task has no stack, so the task isn't in a syscall. */ 13 /* Task has no stack, so the task isn't in a syscall. */
16 *sp = *pc = 0; 14 memset(info, 0, sizeof(*info));
17 *callno = -1; 15 info->data.nr = -1;
18 return 0; 16 return 0;
19 } 17 }
20 18
@@ -24,12 +22,13 @@ static int collect_syscall(struct task_struct *target, long *callno,
24 return -EAGAIN; 22 return -EAGAIN;
25 } 23 }
26 24
27 *sp = user_stack_pointer(regs); 25 info->sp = user_stack_pointer(regs);
28 *pc = instruction_pointer(regs); 26 info->data.instruction_pointer = instruction_pointer(regs);
29 27
30 *callno = syscall_get_nr(target, regs); 28 info->data.nr = syscall_get_nr(target, regs);
31 if (*callno != -1L && maxargs > 0) 29 if (info->data.nr != -1L)
32 syscall_get_arguments(target, regs, 0, maxargs, args); 30 syscall_get_arguments(target, regs,
31 (unsigned long *)&info->data.args[0]);
33 32
34 put_task_stack(target); 33 put_task_stack(target);
35 return 0; 34 return 0;
@@ -38,41 +37,35 @@ static int collect_syscall(struct task_struct *target, long *callno,
38/** 37/**
39 * task_current_syscall - Discover what a blocked task is doing. 38 * task_current_syscall - Discover what a blocked task is doing.
40 * @target: thread to examine 39 * @target: thread to examine
41 * @callno: filled with system call number or -1 40 * @info: structure with the following fields:
42 * @args: filled with @maxargs system call arguments 41 * .sp - filled with user stack pointer
43 * @maxargs: number of elements in @args to fill 42 * .data.nr - filled with system call number or -1
44 * @sp: filled with user stack pointer 43 * .data.args - filled with @maxargs system call arguments
45 * @pc: filled with user PC 44 * .data.instruction_pointer - filled with user PC
46 * 45 *
47 * If @target is blocked in a system call, returns zero with *@callno 46 * If @target is blocked in a system call, returns zero with @info.data.nr
48 * set to the the call's number and @args filled in with its arguments. 47 * set to the the call's number and @info.data.args filled in with its
49 * Registers not used for system call arguments may not be available and 48 * arguments. Registers not used for system call arguments may not be available
50 * it is not kosher to use &struct user_regset calls while the system 49 * and it is not kosher to use &struct user_regset calls while the system
51 * call is still in progress. Note we may get this result if @target 50 * call is still in progress. Note we may get this result if @target
52 * has finished its system call but not yet returned to user mode, such 51 * has finished its system call but not yet returned to user mode, such
53 * as when it's stopped for signal handling or syscall exit tracing. 52 * as when it's stopped for signal handling or syscall exit tracing.
54 * 53 *
55 * If @target is blocked in the kernel during a fault or exception, 54 * If @target is blocked in the kernel during a fault or exception,
56 * returns zero with *@callno set to -1 and does not fill in @args. 55 * returns zero with *@info.data.nr set to -1 and does not fill in
57 * If so, it's now safe to examine @target using &struct user_regset 56 * @info.data.args. If so, it's now safe to examine @target using
58 * get() calls as long as we're sure @target won't return to user mode. 57 * &struct user_regset get() calls as long as we're sure @target won't return
58 * to user mode.
59 * 59 *
60 * Returns -%EAGAIN if @target does not remain blocked. 60 * Returns -%EAGAIN if @target does not remain blocked.
61 *
62 * Returns -%EINVAL if @maxargs is too large (maximum is six).
63 */ 61 */
64int task_current_syscall(struct task_struct *target, long *callno, 62int task_current_syscall(struct task_struct *target, struct syscall_info *info)
65 unsigned long args[6], unsigned int maxargs,
66 unsigned long *sp, unsigned long *pc)
67{ 63{
68 long state; 64 long state;
69 unsigned long ncsw; 65 unsigned long ncsw;
70 66
71 if (unlikely(maxargs > 6))
72 return -EINVAL;
73
74 if (target == current) 67 if (target == current)
75 return collect_syscall(target, callno, args, maxargs, sp, pc); 68 return collect_syscall(target, info);
76 69
77 state = target->state; 70 state = target->state;
78 if (unlikely(!state)) 71 if (unlikely(!state))
@@ -80,7 +73,7 @@ int task_current_syscall(struct task_struct *target, long *callno,
80 73
81 ncsw = wait_task_inactive(target, state); 74 ncsw = wait_task_inactive(target, state);
82 if (unlikely(!ncsw) || 75 if (unlikely(!ncsw) ||
83 unlikely(collect_syscall(target, callno, args, maxargs, sp, pc)) || 76 unlikely(collect_syscall(target, info)) ||
84 unlikely(wait_task_inactive(target, state) != ncsw)) 77 unlikely(wait_task_inactive(target, state) != ncsw))
85 return -EAGAIN; 78 return -EAGAIN;
86 79