mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 23:13:01 +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
|
@ -23,6 +23,17 @@ syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
|
|||
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
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
struct pt_regs *regs,
|
||||
unsigned long *args)
|
||||
|
|
|
@ -26,6 +26,13 @@ static inline long syscall_get_nr(struct task_struct *task,
|
|||
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,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
|
|
|
@ -14,6 +14,13 @@ static inline int syscall_get_nr(struct task_struct *task,
|
|||
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,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
|
|
|
@ -14,6 +14,13 @@ static inline long syscall_get_nr(struct task_struct *task,
|
|||
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,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
|
|
|
@ -41,6 +41,21 @@ static inline long syscall_get_nr(struct task_struct *task,
|
|||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
|
|
|
@ -25,6 +25,12 @@ syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
|
|||
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
|
||||
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];
|
||||
}
|
||||
|
||||
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,
|
||||
struct pt_regs *regs,
|
||||
unsigned long *args)
|
||||
|
|
|
@ -39,6 +39,16 @@ static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
|
|||
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,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
|
|
|
@ -30,6 +30,13 @@ static inline int syscall_get_nr(struct task_struct *task,
|
|||
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,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,18 @@ static inline long syscall_get_nr(struct task_struct *task,
|
|||
(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,
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
|
|
|
@ -28,6 +28,13 @@ static inline long syscall_get_nr(struct task_struct *task,
|
|||
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,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
|
|
|
@ -37,6 +37,20 @@ struct pt_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
|
||||
* @task: task of interest, must be in system call exit tracing
|
||||
|
|
Loading…
Reference in New Issue
Block a user