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

syscall.h: add syscall_set_arguments()

This function is going to be needed on all HAVE_ARCH_TRACEHOOK
architectures to implement PTRACE_SET_SYSCALL_INFO API.

This partially reverts commit 7962c2eddbfe ("arch: remove unused function
syscall_set_arguments()") by reusing some of old syscall_set_arguments()
implementations.

[nathan@kernel.org: fix compile time fortify checks]
Link: https://lkml.kernel.org/r/20250408213131.GA2872426@ax162
Link: https://lkml.kernel.org/r/20250303112009.GC24170@strace.io
Signed-off-by: Dmitry V. Levin <ldv@strace.io>
Signed-off-by: Nathan Chancellor <nathan@kernel.org>
Tested-by: Charlie Jenkins <charlie@rivosinc.com>
Reviewed-by: Charlie Jenkins <charlie@rivosinc.com>
Acked-by: Helge Deller <deller@gmx.de> # parisc
Reviewed-by: Maciej W. Rozycki <macro@orcam.me.uk> [mips]
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Alexey Gladkov (Intel) <legion@kernel.org>
Cc: Andreas Larsson <andreas@gaisler.com>
Cc: anton ivanov <anton.ivanov@cambridgegreys.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Borislav Betkov <bp@alien8.de>
Cc: Brian Cain <bcain@quicinc.com>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Christian Zankel <chris@zankel.net>
Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Davide Berardi <berardi.dav@gmail.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Dinh Nguyen <dinguyen@kernel.org>
Cc: Eugene Syromiatnikov <esyr@redhat.com>
Cc: Eugene Syromyatnikov <evgsyr@gmail.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Guo Ren <guoren@kernel.org>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Cc: Jonas Bonn <jonas@southpole.se>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Max Filippov <jcmvbkbc@gmail.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Michal Simek <monstr@monstr.eu>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Naveen N Rao <naveen@kernel.org>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Renzo Davoi <renzo@cs.unibo.it>
Cc: Richard Weinberger <richard@nod.at>
Cc: Rich Felker <dalias@libc.org>
Cc: Russel King <linux@armlinux.org.uk>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Stafford Horne <shorne@gmail.com>
Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Thomas Gleinxer <tglx@linutronix.de>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Vineet Gupta <vgupta@kernel.org>
Cc: WANG Xuerui <kernel@xen0n.name>
Cc: Will Deacon <will@kernel.org>
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Dmitry V. Levin and committed by
Andrew Morton
17fc7b8f 87a929ae

+256
+14
arch/arc/include/asm/syscall.h
··· 67 67 } 68 68 } 69 69 70 + static inline void 71 + syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, 72 + unsigned long *args) 73 + { 74 + unsigned long *inside_ptregs = &regs->r0; 75 + unsigned int n = 6; 76 + unsigned int i = 0; 77 + 78 + while (n--) { 79 + *inside_ptregs = args[i++]; 80 + inside_ptregs--; 81 + } 82 + } 83 + 70 84 static inline int 71 85 syscall_get_arch(struct task_struct *task) 72 86 {
+13
arch/arm/include/asm/syscall.h
··· 80 80 memcpy(args, &regs->ARM_r0 + 1, 5 * sizeof(args[0])); 81 81 } 82 82 83 + static inline void syscall_set_arguments(struct task_struct *task, 84 + struct pt_regs *regs, 85 + const unsigned long *args) 86 + { 87 + memcpy(&regs->ARM_r0, args, 6 * sizeof(args[0])); 88 + /* 89 + * Also copy the first argument into ARM_ORIG_r0 90 + * so that syscall_get_arguments() would return it 91 + * instead of the previous value. 92 + */ 93 + regs->ARM_ORIG_r0 = regs->ARM_r0; 94 + } 95 + 83 96 static inline int syscall_get_arch(struct task_struct *task) 84 97 { 85 98 /* ARM tasks don't change audit architectures on the fly. */
+13
arch/arm64/include/asm/syscall.h
··· 73 73 memcpy(args, &regs->regs[1], 5 * sizeof(args[0])); 74 74 } 75 75 76 + static inline void syscall_set_arguments(struct task_struct *task, 77 + struct pt_regs *regs, 78 + const unsigned long *args) 79 + { 80 + memcpy(&regs->regs[0], args, 6 * sizeof(args[0])); 81 + /* 82 + * Also copy the first argument into orig_x0 83 + * so that syscall_get_arguments() would return it 84 + * instead of the previous value. 85 + */ 86 + regs->orig_x0 = regs->regs[0]; 87 + } 88 + 76 89 /* 77 90 * We don't care about endianness (__AUDIT_ARCH_LE bit) here because 78 91 * AArch64 has the same system calls both on little- and big- endian.
+13
arch/csky/include/asm/syscall.h
··· 59 59 memcpy(args, &regs->a1, 5 * sizeof(args[0])); 60 60 } 61 61 62 + static inline void 63 + syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, 64 + const unsigned long *args) 65 + { 66 + memcpy(&regs->a0, args, 6 * sizeof(regs->a0)); 67 + /* 68 + * Also copy the first argument into orig_a0 69 + * so that syscall_get_arguments() would return it 70 + * instead of the previous value. 71 + */ 72 + regs->orig_a0 = regs->a0; 73 + } 74 + 62 75 static inline int 63 76 syscall_get_arch(struct task_struct *task) 64 77 {
+7
arch/hexagon/include/asm/syscall.h
··· 33 33 memcpy(args, &(&regs->r00)[0], 6 * sizeof(args[0])); 34 34 } 35 35 36 + static inline void syscall_set_arguments(struct task_struct *task, 37 + struct pt_regs *regs, 38 + unsigned long *args) 39 + { 40 + memcpy(&(&regs->r00)[0], args, 6 * sizeof(args[0])); 41 + } 42 + 36 43 static inline long syscall_get_error(struct task_struct *task, 37 44 struct pt_regs *regs) 38 45 {
+8
arch/loongarch/include/asm/syscall.h
··· 61 61 memcpy(&args[1], &regs->regs[5], 5 * sizeof(long)); 62 62 } 63 63 64 + static inline void syscall_set_arguments(struct task_struct *task, 65 + struct pt_regs *regs, 66 + unsigned long *args) 67 + { 68 + regs->orig_a0 = args[0]; 69 + memcpy(&regs->regs[5], &args[1], 5 * sizeof(long)); 70 + } 71 + 64 72 static inline int syscall_get_arch(struct task_struct *task) 65 73 { 66 74 return AUDIT_ARCH_LOONGARCH64;
+28
arch/mips/include/asm/syscall.h
··· 74 74 #endif 75 75 } 76 76 77 + static inline void mips_set_syscall_arg(unsigned long *arg, 78 + struct task_struct *task, struct pt_regs *regs, unsigned int n) 79 + { 80 + #ifdef CONFIG_32BIT 81 + switch (n) { 82 + case 0: case 1: case 2: case 3: 83 + regs->regs[4 + n] = *arg; 84 + return; 85 + case 4: case 5: case 6: case 7: 86 + *arg = regs->args[n] = *arg; 87 + return; 88 + } 89 + #else 90 + regs->regs[4 + n] = *arg; 91 + #endif 92 + } 93 + 77 94 static inline long syscall_get_error(struct task_struct *task, 78 95 struct pt_regs *regs) 79 96 { ··· 135 118 136 119 while (n--) 137 120 mips_get_syscall_arg(args++, task, regs, i++); 121 + } 122 + 123 + static inline void syscall_set_arguments(struct task_struct *task, 124 + struct pt_regs *regs, 125 + unsigned long *args) 126 + { 127 + unsigned int i = 0; 128 + unsigned int n = 6; 129 + 130 + while (n--) 131 + mips_set_syscall_arg(args++, task, regs, i++); 138 132 } 139 133 140 134 extern const unsigned long sys_call_table[];
+11
arch/nios2/include/asm/syscall.h
··· 58 58 *args = regs->r9; 59 59 } 60 60 61 + static inline void syscall_set_arguments(struct task_struct *task, 62 + struct pt_regs *regs, const unsigned long *args) 63 + { 64 + regs->r4 = *args++; 65 + regs->r5 = *args++; 66 + regs->r6 = *args++; 67 + regs->r7 = *args++; 68 + regs->r8 = *args++; 69 + regs->r9 = *args; 70 + } 71 + 61 72 static inline int syscall_get_arch(struct task_struct *task) 62 73 { 63 74 return AUDIT_ARCH_NIOS2;
+7
arch/openrisc/include/asm/syscall.h
··· 57 57 memcpy(args, &regs->gpr[3], 6 * sizeof(args[0])); 58 58 } 59 59 60 + static inline void 61 + syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, 62 + const unsigned long *args) 63 + { 64 + memcpy(&regs->gpr[3], args, 6 * sizeof(args[0])); 65 + } 66 + 60 67 static inline int syscall_get_arch(struct task_struct *task) 61 68 { 62 69 return AUDIT_ARCH_OPENRISC;
+12
arch/parisc/include/asm/syscall.h
··· 29 29 args[0] = regs->gr[26]; 30 30 } 31 31 32 + static inline void syscall_set_arguments(struct task_struct *tsk, 33 + struct pt_regs *regs, 34 + unsigned long *args) 35 + { 36 + regs->gr[21] = args[5]; 37 + regs->gr[22] = args[4]; 38 + regs->gr[23] = args[3]; 39 + regs->gr[24] = args[2]; 40 + regs->gr[25] = args[1]; 41 + regs->gr[26] = args[0]; 42 + } 43 + 32 44 static inline long syscall_get_error(struct task_struct *task, 33 45 struct pt_regs *regs) 34 46 {
+10
arch/powerpc/include/asm/syscall.h
··· 110 110 } 111 111 } 112 112 113 + static inline void syscall_set_arguments(struct task_struct *task, 114 + struct pt_regs *regs, 115 + const unsigned long *args) 116 + { 117 + memcpy(&regs->gpr[3], args, 6 * sizeof(args[0])); 118 + 119 + /* Also copy the first argument into orig_gpr3 */ 120 + regs->orig_gpr3 = args[0]; 121 + } 122 + 113 123 static inline int syscall_get_arch(struct task_struct *task) 114 124 { 115 125 if (is_tsk_32bit_task(task))
+12
arch/riscv/include/asm/syscall.h
··· 69 69 args[5] = regs->a5; 70 70 } 71 71 72 + static inline void syscall_set_arguments(struct task_struct *task, 73 + struct pt_regs *regs, 74 + const unsigned long *args) 75 + { 76 + regs->orig_a0 = args[0]; 77 + regs->a1 = args[1]; 78 + regs->a2 = args[2]; 79 + regs->a3 = args[3]; 80 + regs->a4 = args[4]; 81 + regs->a5 = args[5]; 82 + } 83 + 72 84 static inline int syscall_get_arch(struct task_struct *task) 73 85 { 74 86 #ifdef CONFIG_64BIT
+9
arch/s390/include/asm/syscall.h
··· 76 76 args[0] = regs->orig_gpr2 & mask; 77 77 } 78 78 79 + static inline void syscall_set_arguments(struct task_struct *task, 80 + struct pt_regs *regs, 81 + const unsigned long *args) 82 + { 83 + regs->orig_gpr2 = args[0]; 84 + for (int n = 1; n < 6; n++) 85 + regs->gprs[2 + n] = args[n]; 86 + } 87 + 79 88 static inline int syscall_get_arch(struct task_struct *task) 80 89 { 81 90 #ifdef CONFIG_COMPAT
+12
arch/sh/include/asm/syscall_32.h
··· 57 57 args[0] = regs->regs[4]; 58 58 } 59 59 60 + static inline void syscall_set_arguments(struct task_struct *task, 61 + struct pt_regs *regs, 62 + const unsigned long *args) 63 + { 64 + regs->regs[1] = args[5]; 65 + regs->regs[0] = args[4]; 66 + regs->regs[7] = args[3]; 67 + regs->regs[6] = args[2]; 68 + regs->regs[5] = args[1]; 69 + regs->regs[4] = args[0]; 70 + } 71 + 60 72 static inline int syscall_get_arch(struct task_struct *task) 61 73 { 62 74 int arch = AUDIT_ARCH_SH;
+10
arch/sparc/include/asm/syscall.h
··· 117 117 } 118 118 } 119 119 120 + static inline void syscall_set_arguments(struct task_struct *task, 121 + struct pt_regs *regs, 122 + const unsigned long *args) 123 + { 124 + unsigned int i; 125 + 126 + for (i = 0; i < 6; i++) 127 + regs->u_regs[UREG_I0 + i] = args[i]; 128 + } 129 + 120 130 static inline int syscall_get_arch(struct task_struct *task) 121 131 { 122 132 #if defined(CONFIG_SPARC64) && defined(CONFIG_COMPAT)
+14
arch/um/include/asm/syscall-generic.h
··· 62 62 *args = UPT_SYSCALL_ARG6(r); 63 63 } 64 64 65 + static inline void syscall_set_arguments(struct task_struct *task, 66 + struct pt_regs *regs, 67 + const unsigned long *args) 68 + { 69 + struct uml_pt_regs *r = &regs->regs; 70 + 71 + UPT_SYSCALL_ARG1(r) = *args++; 72 + UPT_SYSCALL_ARG2(r) = *args++; 73 + UPT_SYSCALL_ARG3(r) = *args++; 74 + UPT_SYSCALL_ARG4(r) = *args++; 75 + UPT_SYSCALL_ARG5(r) = *args++; 76 + UPT_SYSCALL_ARG6(r) = *args; 77 + } 78 + 65 79 /* See arch/x86/um/asm/syscall.h for syscall_get_arch() definition. */ 66 80 67 81 #endif /* __UM_SYSCALL_GENERIC_H */
+36
arch/x86/include/asm/syscall.h
··· 90 90 args[5] = regs->bp; 91 91 } 92 92 93 + static inline void syscall_set_arguments(struct task_struct *task, 94 + struct pt_regs *regs, 95 + const unsigned long *args) 96 + { 97 + regs->bx = args[0]; 98 + regs->cx = args[1]; 99 + regs->dx = args[2]; 100 + regs->si = args[3]; 101 + regs->di = args[4]; 102 + regs->bp = args[5]; 103 + } 104 + 93 105 static inline int syscall_get_arch(struct task_struct *task) 94 106 { 95 107 return AUDIT_ARCH_I386; ··· 130 118 *args++ = regs->r10; 131 119 *args++ = regs->r8; 132 120 *args = regs->r9; 121 + } 122 + } 123 + 124 + static inline void syscall_set_arguments(struct task_struct *task, 125 + struct pt_regs *regs, 126 + const unsigned long *args) 127 + { 128 + # ifdef CONFIG_IA32_EMULATION 129 + if (task->thread_info.status & TS_COMPAT) { 130 + regs->bx = *args++; 131 + regs->cx = *args++; 132 + regs->dx = *args++; 133 + regs->si = *args++; 134 + regs->di = *args++; 135 + regs->bp = *args; 136 + } else 137 + # endif 138 + { 139 + regs->di = *args++; 140 + regs->si = *args++; 141 + regs->dx = *args++; 142 + regs->r10 = *args++; 143 + regs->r8 = *args++; 144 + regs->r9 = *args; 133 145 } 134 146 } 135 147
+11
arch/xtensa/include/asm/syscall.h
··· 68 68 args[i] = regs->areg[reg[i]]; 69 69 } 70 70 71 + static inline void syscall_set_arguments(struct task_struct *task, 72 + struct pt_regs *regs, 73 + const unsigned long *args) 74 + { 75 + static const unsigned int reg[] = XTENSA_SYSCALL_ARGUMENT_REGS; 76 + unsigned int i; 77 + 78 + for (i = 0; i < 6; ++i) 79 + regs->areg[reg[i]] = args[i]; 80 + } 81 + 71 82 asmlinkage long xtensa_rt_sigreturn(void); 72 83 asmlinkage long xtensa_shmat(int, char __user *, int); 73 84 asmlinkage long xtensa_fadvise64_64(int, int,
+16
include/asm-generic/syscall.h
··· 118 118 unsigned long *args); 119 119 120 120 /** 121 + * syscall_set_arguments - change system call parameter value 122 + * @task: task of interest, must be in system call entry tracing 123 + * @regs: task_pt_regs() of @task 124 + * @args: array of argument values to store 125 + * 126 + * Changes 6 arguments to the system call. 127 + * The first argument gets value @args[0], and so on. 128 + * 129 + * It's only valid to call this when @task is stopped for tracing on 130 + * entry to a system call, due to %SYSCALL_WORK_SYSCALL_TRACE or 131 + * %SYSCALL_WORK_SYSCALL_AUDIT. 132 + */ 133 + void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, 134 + const unsigned long *args); 135 + 136 + /** 121 137 * syscall_get_arch - return the AUDIT_ARCH for the current system call 122 138 * @task: task of interest, must be blocked 123 139 *