mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	syscall.h: introduce syscall_set_nr()
Similar to syscall_set_arguments() that complements syscall_get_arguments(), introduce syscall_set_nr() that complements syscall_get_nr(). syscall_set_nr() is going to be needed along with syscall_set_arguments() on all HAVE_ARCH_TRACEHOOK architectures to implement PTRACE_SET_SYSCALL_INFO API. Link: https://lkml.kernel.org/r/20250303112020.GD24170@strace.io Signed-off-by: Dmitry V. Levin <ldv@strace.io> 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>
This commit is contained in:
		
							parent
							
								
									17fc7b8f9b
								
							
						
					
					
						commit
						cc6622730b
					
				
					 20 changed files with 198 additions and 0 deletions
				
			
		| 
						 | 
					@ -23,6 +23,17 @@ syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void
 | 
				
			||||||
 | 
					syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Unlike syscall_get_nr(), syscall_set_nr() can be called only when
 | 
				
			||||||
 | 
						 * the target task is stopped for tracing on entering syscall, so
 | 
				
			||||||
 | 
						 * there is no need to have the same check syscall_get_nr() has.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						regs->r8 = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void
 | 
					static inline void
 | 
				
			||||||
syscall_rollback(struct task_struct *task, struct pt_regs *regs)
 | 
					syscall_rollback(struct task_struct *task, struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,6 +68,30 @@ static inline void syscall_set_return_value(struct task_struct *task,
 | 
				
			||||||
	regs->ARM_r0 = (long) error ? error : val;
 | 
						regs->ARM_r0 = (long) error ? error : val;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task,
 | 
				
			||||||
 | 
									  struct pt_regs *regs,
 | 
				
			||||||
 | 
									  int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (nr == -1) {
 | 
				
			||||||
 | 
							task_thread_info(task)->abi_syscall = -1;
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * When the syscall number is set to -1, the syscall will be
 | 
				
			||||||
 | 
							 * skipped.  In this case the syscall return value has to be
 | 
				
			||||||
 | 
							 * set explicitly, otherwise the first syscall argument is
 | 
				
			||||||
 | 
							 * returned as the syscall return value.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							syscall_set_return_value(task, regs, -ENOSYS, 0);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if ((IS_ENABLED(CONFIG_AEABI) && !IS_ENABLED(CONFIG_OABI_COMPAT))) {
 | 
				
			||||||
 | 
							task_thread_info(task)->abi_syscall = nr;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						task_thread_info(task)->abi_syscall =
 | 
				
			||||||
 | 
							(task_thread_info(task)->abi_syscall & ~__NR_SYSCALL_MASK) |
 | 
				
			||||||
 | 
							(nr & __NR_SYSCALL_MASK);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SYSCALL_MAX_ARGS 7
 | 
					#define SYSCALL_MAX_ARGS 7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_get_arguments(struct task_struct *task,
 | 
					static inline void syscall_get_arguments(struct task_struct *task,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,6 +61,22 @@ static inline void syscall_set_return_value(struct task_struct *task,
 | 
				
			||||||
	regs->regs[0] = val;
 | 
						regs->regs[0] = val;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task,
 | 
				
			||||||
 | 
									  struct pt_regs *regs,
 | 
				
			||||||
 | 
									  int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						regs->syscallno = nr;
 | 
				
			||||||
 | 
						if (nr == -1) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * When the syscall number is set to -1, the syscall will be
 | 
				
			||||||
 | 
							 * skipped.  In this case the syscall return value has to be
 | 
				
			||||||
 | 
							 * set explicitly, otherwise the first syscall argument is
 | 
				
			||||||
 | 
							 * returned as the syscall return value.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							syscall_set_return_value(task, regs, -ENOSYS, 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SYSCALL_MAX_ARGS 6
 | 
					#define SYSCALL_MAX_ARGS 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_get_arguments(struct task_struct *task,
 | 
					static inline void syscall_get_arguments(struct task_struct *task,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,13 @@ static inline long syscall_get_nr(struct task_struct *task,
 | 
				
			||||||
	return regs->r06;
 | 
						return regs->r06;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task,
 | 
				
			||||||
 | 
									  struct pt_regs *regs,
 | 
				
			||||||
 | 
									  int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						regs->r06 = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_get_arguments(struct task_struct *task,
 | 
					static inline void syscall_get_arguments(struct task_struct *task,
 | 
				
			||||||
					 struct pt_regs *regs,
 | 
										 struct pt_regs *regs,
 | 
				
			||||||
					 unsigned long *args)
 | 
										 unsigned long *args)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,13 @@ static inline long syscall_get_nr(struct task_struct *task,
 | 
				
			||||||
	return regs->regs[11];
 | 
						return regs->regs[11];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task,
 | 
				
			||||||
 | 
									  struct pt_regs *regs,
 | 
				
			||||||
 | 
									  int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						regs->regs[11] = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_rollback(struct task_struct *task,
 | 
					static inline void syscall_rollback(struct task_struct *task,
 | 
				
			||||||
				    struct pt_regs *regs)
 | 
									    struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,13 @@ static inline int syscall_get_nr(struct task_struct *task,
 | 
				
			||||||
	return regs->orig_d0;
 | 
						return regs->orig_d0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task,
 | 
				
			||||||
 | 
									  struct pt_regs *regs,
 | 
				
			||||||
 | 
									  int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						regs->orig_d0 = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_rollback(struct task_struct *task,
 | 
					static inline void syscall_rollback(struct task_struct *task,
 | 
				
			||||||
				    struct pt_regs *regs)
 | 
									    struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,13 @@ static inline long syscall_get_nr(struct task_struct *task,
 | 
				
			||||||
	return regs->r12;
 | 
						return regs->r12;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task,
 | 
				
			||||||
 | 
									  struct pt_regs *regs,
 | 
				
			||||||
 | 
									  int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						regs->r12 = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_rollback(struct task_struct *task,
 | 
					static inline void syscall_rollback(struct task_struct *task,
 | 
				
			||||||
				    struct pt_regs *regs)
 | 
									    struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,6 +41,21 @@ static inline long syscall_get_nr(struct task_struct *task,
 | 
				
			||||||
	return task_thread_info(task)->syscall;
 | 
						return task_thread_info(task)->syscall;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task,
 | 
				
			||||||
 | 
									  struct pt_regs *regs,
 | 
				
			||||||
 | 
									  int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * New syscall number has to be assigned to regs[2] because
 | 
				
			||||||
 | 
						 * it is loaded from there unconditionally after return from
 | 
				
			||||||
 | 
						 * syscall_trace_enter() invocation.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Consequently, if the syscall was indirect and nr != __NR_syscall,
 | 
				
			||||||
 | 
						 * then after this assignment the syscall will cease to be indirect.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						task_thread_info(task)->syscall = regs->regs[2] = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void mips_syscall_update_nr(struct task_struct *task,
 | 
					static inline void mips_syscall_update_nr(struct task_struct *task,
 | 
				
			||||||
					  struct pt_regs *regs)
 | 
										  struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,11 @@ static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
 | 
				
			||||||
	return regs->r2;
 | 
						return regs->r2;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						regs->r2 = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_rollback(struct task_struct *task,
 | 
					static inline void syscall_rollback(struct task_struct *task,
 | 
				
			||||||
				struct pt_regs *regs)
 | 
									struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,12 @@ syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
 | 
				
			||||||
	return regs->orig_gpr11;
 | 
						return regs->orig_gpr11;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void
 | 
				
			||||||
 | 
					syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						regs->orig_gpr11 = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void
 | 
					static inline void
 | 
				
			||||||
syscall_rollback(struct task_struct *task, struct pt_regs *regs)
 | 
					syscall_rollback(struct task_struct *task, struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,6 +17,13 @@ static inline long syscall_get_nr(struct task_struct *tsk,
 | 
				
			||||||
	return regs->gr[20];
 | 
						return regs->gr[20];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *tsk,
 | 
				
			||||||
 | 
									  struct pt_regs *regs,
 | 
				
			||||||
 | 
									  int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						regs->gr[20] = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_get_arguments(struct task_struct *tsk,
 | 
					static inline void syscall_get_arguments(struct task_struct *tsk,
 | 
				
			||||||
					 struct pt_regs *regs,
 | 
										 struct pt_regs *regs,
 | 
				
			||||||
					 unsigned long *args)
 | 
										 unsigned long *args)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,6 +39,16 @@ static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Unlike syscall_get_nr(), syscall_set_nr() can be called only when
 | 
				
			||||||
 | 
						 * the target task is stopped for tracing on entering syscall, so
 | 
				
			||||||
 | 
						 * there is no need to have the same check syscall_get_nr() has.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						regs->gpr[0] = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_rollback(struct task_struct *task,
 | 
					static inline void syscall_rollback(struct task_struct *task,
 | 
				
			||||||
				    struct pt_regs *regs)
 | 
									    struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,6 +30,13 @@ static inline int syscall_get_nr(struct task_struct *task,
 | 
				
			||||||
	return regs->a7;
 | 
						return regs->a7;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task,
 | 
				
			||||||
 | 
									  struct pt_regs *regs,
 | 
				
			||||||
 | 
									  int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						regs->a7 = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_rollback(struct task_struct *task,
 | 
					static inline void syscall_rollback(struct task_struct *task,
 | 
				
			||||||
				    struct pt_regs *regs)
 | 
									    struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,18 @@ static inline long syscall_get_nr(struct task_struct *task,
 | 
				
			||||||
		(regs->int_code & 0xffff) : -1;
 | 
							(regs->int_code & 0xffff) : -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task,
 | 
				
			||||||
 | 
									  struct pt_regs *regs,
 | 
				
			||||||
 | 
									  int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Unlike syscall_get_nr(), syscall_set_nr() can be called only when
 | 
				
			||||||
 | 
						 * the target task is stopped for tracing on entering syscall, so
 | 
				
			||||||
 | 
						 * there is no need to have the same check syscall_get_nr() has.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						regs->int_code = (regs->int_code & ~0xffff) | (nr & 0xffff);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_rollback(struct task_struct *task,
 | 
					static inline void syscall_rollback(struct task_struct *task,
 | 
				
			||||||
				    struct pt_regs *regs)
 | 
									    struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,18 @@ static inline long syscall_get_nr(struct task_struct *task,
 | 
				
			||||||
	return (regs->tra >= 0) ? regs->regs[3] : -1L;
 | 
						return (regs->tra >= 0) ? regs->regs[3] : -1L;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task,
 | 
				
			||||||
 | 
									  struct pt_regs *regs,
 | 
				
			||||||
 | 
									  int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Unlike syscall_get_nr(), syscall_set_nr() can be called only when
 | 
				
			||||||
 | 
						 * the target task is stopped for tracing on entering syscall, so
 | 
				
			||||||
 | 
						 * there is no need to have the same check syscall_get_nr() has.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						regs->regs[3] = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_rollback(struct task_struct *task,
 | 
					static inline void syscall_rollback(struct task_struct *task,
 | 
				
			||||||
				    struct pt_regs *regs)
 | 
									    struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,18 @@ static inline long syscall_get_nr(struct task_struct *task,
 | 
				
			||||||
	return (syscall_p ? regs->u_regs[UREG_G1] : -1L);
 | 
						return (syscall_p ? regs->u_regs[UREG_G1] : -1L);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task,
 | 
				
			||||||
 | 
									  struct pt_regs *regs,
 | 
				
			||||||
 | 
									  int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Unlike syscall_get_nr(), syscall_set_nr() can be called only when
 | 
				
			||||||
 | 
						 * the target task is stopped for tracing on entering syscall, so
 | 
				
			||||||
 | 
						 * there is no need to have the same check syscall_get_nr() has.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						regs->u_regs[UREG_G1] = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_rollback(struct task_struct *task,
 | 
					static inline void syscall_rollback(struct task_struct *task,
 | 
				
			||||||
				    struct pt_regs *regs)
 | 
									    struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,11 @@ static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
 | 
				
			||||||
	return PT_REGS_SYSCALL_NR(regs);
 | 
						return PT_REGS_SYSCALL_NR(regs);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PT_REGS_SYSCALL_NR(regs) = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_rollback(struct task_struct *task,
 | 
					static inline void syscall_rollback(struct task_struct *task,
 | 
				
			||||||
				    struct pt_regs *regs)
 | 
									    struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,6 +38,13 @@ static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
 | 
				
			||||||
	return regs->orig_ax;
 | 
						return regs->orig_ax;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task,
 | 
				
			||||||
 | 
									  struct pt_regs *regs,
 | 
				
			||||||
 | 
									  int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						regs->orig_ax = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_rollback(struct task_struct *task,
 | 
					static inline void syscall_rollback(struct task_struct *task,
 | 
				
			||||||
				    struct pt_regs *regs)
 | 
									    struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +28,13 @@ static inline long syscall_get_nr(struct task_struct *task,
 | 
				
			||||||
	return regs->syscall;
 | 
						return regs->syscall;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void syscall_set_nr(struct task_struct *task,
 | 
				
			||||||
 | 
									  struct pt_regs *regs,
 | 
				
			||||||
 | 
									  int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						regs->syscall = nr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void syscall_rollback(struct task_struct *task,
 | 
					static inline void syscall_rollback(struct task_struct *task,
 | 
				
			||||||
				    struct pt_regs *regs)
 | 
									    struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,20 @@ struct pt_regs;
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int syscall_get_nr(struct task_struct *task, struct pt_regs *regs);
 | 
					int syscall_get_nr(struct task_struct *task, struct pt_regs *regs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * syscall_set_nr - change the system call a task is executing
 | 
				
			||||||
 | 
					 * @task:	task of interest, must be blocked
 | 
				
			||||||
 | 
					 * @regs:	task_pt_regs() of @task
 | 
				
			||||||
 | 
					 * @nr:		system call number
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Changes the system call number @task is about to execute.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * It's only valid to call this when @task is stopped for tracing on
 | 
				
			||||||
 | 
					 * entry to a system call, due to %SYSCALL_WORK_SYSCALL_TRACE or
 | 
				
			||||||
 | 
					 * %SYSCALL_WORK_SYSCALL_AUDIT.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * syscall_rollback - roll back registers after an aborted system call
 | 
					 * syscall_rollback - roll back registers after an aborted system call
 | 
				
			||||||
 * @task:	task of interest, must be in system call exit tracing
 | 
					 * @task:	task of interest, must be in system call exit tracing
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue