Skip to content

Commit cc66227

Browse files
ldv-altakpm00
authored andcommitted
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>
1 parent 17fc7b8 commit cc66227

File tree

20 files changed

+198
-0
lines changed

20 files changed

+198
-0
lines changed

arch/arc/include/asm/syscall.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@ syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
2323
return -1;
2424
}
2525

26+
static inline void
27+
syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr)
28+
{
29+
/*
30+
* Unlike syscall_get_nr(), syscall_set_nr() can be called only when
31+
* the target task is stopped for tracing on entering syscall, so
32+
* there is no need to have the same check syscall_get_nr() has.
33+
*/
34+
regs->r8 = nr;
35+
}
36+
2637
static inline void
2738
syscall_rollback(struct task_struct *task, struct pt_regs *regs)
2839
{

arch/arm/include/asm/syscall.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,30 @@ static inline void syscall_set_return_value(struct task_struct *task,
6868
regs->ARM_r0 = (long) error ? error : val;
6969
}
7070

71+
static inline void syscall_set_nr(struct task_struct *task,
72+
struct pt_regs *regs,
73+
int nr)
74+
{
75+
if (nr == -1) {
76+
task_thread_info(task)->abi_syscall = -1;
77+
/*
78+
* When the syscall number is set to -1, the syscall will be
79+
* skipped. In this case the syscall return value has to be
80+
* set explicitly, otherwise the first syscall argument is
81+
* returned as the syscall return value.
82+
*/
83+
syscall_set_return_value(task, regs, -ENOSYS, 0);
84+
return;
85+
}
86+
if ((IS_ENABLED(CONFIG_AEABI) && !IS_ENABLED(CONFIG_OABI_COMPAT))) {
87+
task_thread_info(task)->abi_syscall = nr;
88+
return;
89+
}
90+
task_thread_info(task)->abi_syscall =
91+
(task_thread_info(task)->abi_syscall & ~__NR_SYSCALL_MASK) |
92+
(nr & __NR_SYSCALL_MASK);
93+
}
94+
7195
#define SYSCALL_MAX_ARGS 7
7296

7397
static inline void syscall_get_arguments(struct task_struct *task,

arch/arm64/include/asm/syscall.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,22 @@ static inline void syscall_set_return_value(struct task_struct *task,
6161
regs->regs[0] = val;
6262
}
6363

64+
static inline void syscall_set_nr(struct task_struct *task,
65+
struct pt_regs *regs,
66+
int nr)
67+
{
68+
regs->syscallno = nr;
69+
if (nr == -1) {
70+
/*
71+
* When the syscall number is set to -1, the syscall will be
72+
* skipped. In this case the syscall return value has to be
73+
* set explicitly, otherwise the first syscall argument is
74+
* returned as the syscall return value.
75+
*/
76+
syscall_set_return_value(task, regs, -ENOSYS, 0);
77+
}
78+
}
79+
6480
#define SYSCALL_MAX_ARGS 6
6581

6682
static inline void syscall_get_arguments(struct task_struct *task,

arch/hexagon/include/asm/syscall.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ static inline long syscall_get_nr(struct task_struct *task,
2626
return regs->r06;
2727
}
2828

29+
static inline void syscall_set_nr(struct task_struct *task,
30+
struct pt_regs *regs,
31+
int nr)
32+
{
33+
regs->r06 = nr;
34+
}
35+
2936
static inline void syscall_get_arguments(struct task_struct *task,
3037
struct pt_regs *regs,
3138
unsigned long *args)

arch/loongarch/include/asm/syscall.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ static inline long syscall_get_nr(struct task_struct *task,
2626
return regs->regs[11];
2727
}
2828

29+
static inline void syscall_set_nr(struct task_struct *task,
30+
struct pt_regs *regs,
31+
int nr)
32+
{
33+
regs->regs[11] = nr;
34+
}
35+
2936
static inline void syscall_rollback(struct task_struct *task,
3037
struct pt_regs *regs)
3138
{

arch/m68k/include/asm/syscall.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ static inline int syscall_get_nr(struct task_struct *task,
1414
return regs->orig_d0;
1515
}
1616

17+
static inline void syscall_set_nr(struct task_struct *task,
18+
struct pt_regs *regs,
19+
int nr)
20+
{
21+
regs->orig_d0 = nr;
22+
}
23+
1724
static inline void syscall_rollback(struct task_struct *task,
1825
struct pt_regs *regs)
1926
{

arch/microblaze/include/asm/syscall.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ static inline long syscall_get_nr(struct task_struct *task,
1414
return regs->r12;
1515
}
1616

17+
static inline void syscall_set_nr(struct task_struct *task,
18+
struct pt_regs *regs,
19+
int nr)
20+
{
21+
regs->r12 = nr;
22+
}
23+
1724
static inline void syscall_rollback(struct task_struct *task,
1825
struct pt_regs *regs)
1926
{

arch/mips/include/asm/syscall.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,21 @@ static inline long syscall_get_nr(struct task_struct *task,
4141
return task_thread_info(task)->syscall;
4242
}
4343

44+
static inline void syscall_set_nr(struct task_struct *task,
45+
struct pt_regs *regs,
46+
int nr)
47+
{
48+
/*
49+
* New syscall number has to be assigned to regs[2] because
50+
* it is loaded from there unconditionally after return from
51+
* syscall_trace_enter() invocation.
52+
*
53+
* Consequently, if the syscall was indirect and nr != __NR_syscall,
54+
* then after this assignment the syscall will cease to be indirect.
55+
*/
56+
task_thread_info(task)->syscall = regs->regs[2] = nr;
57+
}
58+
4459
static inline void mips_syscall_update_nr(struct task_struct *task,
4560
struct pt_regs *regs)
4661
{

arch/nios2/include/asm/syscall.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
1515
return regs->r2;
1616
}
1717

18+
static inline void syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr)
19+
{
20+
regs->r2 = nr;
21+
}
22+
1823
static inline void syscall_rollback(struct task_struct *task,
1924
struct pt_regs *regs)
2025
{

arch/openrisc/include/asm/syscall.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
2525
return regs->orig_gpr11;
2626
}
2727

28+
static inline void
29+
syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr)
30+
{
31+
regs->orig_gpr11 = nr;
32+
}
33+
2834
static inline void
2935
syscall_rollback(struct task_struct *task, struct pt_regs *regs)
3036
{

arch/parisc/include/asm/syscall.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ static inline long syscall_get_nr(struct task_struct *tsk,
1717
return regs->gr[20];
1818
}
1919

20+
static inline void syscall_set_nr(struct task_struct *tsk,
21+
struct pt_regs *regs,
22+
int nr)
23+
{
24+
regs->gr[20] = nr;
25+
}
26+
2027
static inline void syscall_get_arguments(struct task_struct *tsk,
2128
struct pt_regs *regs,
2229
unsigned long *args)

arch/powerpc/include/asm/syscall.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
3939
return -1;
4040
}
4141

42+
static inline void syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr)
43+
{
44+
/*
45+
* Unlike syscall_get_nr(), syscall_set_nr() can be called only when
46+
* the target task is stopped for tracing on entering syscall, so
47+
* there is no need to have the same check syscall_get_nr() has.
48+
*/
49+
regs->gpr[0] = nr;
50+
}
51+
4252
static inline void syscall_rollback(struct task_struct *task,
4353
struct pt_regs *regs)
4454
{

arch/riscv/include/asm/syscall.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ static inline int syscall_get_nr(struct task_struct *task,
3030
return regs->a7;
3131
}
3232

33+
static inline void syscall_set_nr(struct task_struct *task,
34+
struct pt_regs *regs,
35+
int nr)
36+
{
37+
regs->a7 = nr;
38+
}
39+
3340
static inline void syscall_rollback(struct task_struct *task,
3441
struct pt_regs *regs)
3542
{

arch/s390/include/asm/syscall.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ static inline long syscall_get_nr(struct task_struct *task,
2424
(regs->int_code & 0xffff) : -1;
2525
}
2626

27+
static inline void syscall_set_nr(struct task_struct *task,
28+
struct pt_regs *regs,
29+
int nr)
30+
{
31+
/*
32+
* Unlike syscall_get_nr(), syscall_set_nr() can be called only when
33+
* the target task is stopped for tracing on entering syscall, so
34+
* there is no need to have the same check syscall_get_nr() has.
35+
*/
36+
regs->int_code = (regs->int_code & ~0xffff) | (nr & 0xffff);
37+
}
38+
2739
static inline void syscall_rollback(struct task_struct *task,
2840
struct pt_regs *regs)
2941
{

arch/sh/include/asm/syscall_32.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,18 @@ static inline long syscall_get_nr(struct task_struct *task,
1515
return (regs->tra >= 0) ? regs->regs[3] : -1L;
1616
}
1717

18+
static inline void syscall_set_nr(struct task_struct *task,
19+
struct pt_regs *regs,
20+
int nr)
21+
{
22+
/*
23+
* Unlike syscall_get_nr(), syscall_set_nr() can be called only when
24+
* the target task is stopped for tracing on entering syscall, so
25+
* there is no need to have the same check syscall_get_nr() has.
26+
*/
27+
regs->regs[3] = nr;
28+
}
29+
1830
static inline void syscall_rollback(struct task_struct *task,
1931
struct pt_regs *regs)
2032
{

arch/sparc/include/asm/syscall.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ static inline long syscall_get_nr(struct task_struct *task,
2525
return (syscall_p ? regs->u_regs[UREG_G1] : -1L);
2626
}
2727

28+
static inline void syscall_set_nr(struct task_struct *task,
29+
struct pt_regs *regs,
30+
int nr)
31+
{
32+
/*
33+
* Unlike syscall_get_nr(), syscall_set_nr() can be called only when
34+
* the target task is stopped for tracing on entering syscall, so
35+
* there is no need to have the same check syscall_get_nr() has.
36+
*/
37+
regs->u_regs[UREG_G1] = nr;
38+
}
39+
2840
static inline void syscall_rollback(struct task_struct *task,
2941
struct pt_regs *regs)
3042
{

arch/um/include/asm/syscall-generic.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
2121
return PT_REGS_SYSCALL_NR(regs);
2222
}
2323

24+
static inline void syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr)
25+
{
26+
PT_REGS_SYSCALL_NR(regs) = nr;
27+
}
28+
2429
static inline void syscall_rollback(struct task_struct *task,
2530
struct pt_regs *regs)
2631
{

arch/x86/include/asm/syscall.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
3838
return regs->orig_ax;
3939
}
4040

41+
static inline void syscall_set_nr(struct task_struct *task,
42+
struct pt_regs *regs,
43+
int nr)
44+
{
45+
regs->orig_ax = nr;
46+
}
47+
4148
static inline void syscall_rollback(struct task_struct *task,
4249
struct pt_regs *regs)
4350
{

arch/xtensa/include/asm/syscall.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ static inline long syscall_get_nr(struct task_struct *task,
2828
return regs->syscall;
2929
}
3030

31+
static inline void syscall_set_nr(struct task_struct *task,
32+
struct pt_regs *regs,
33+
int nr)
34+
{
35+
regs->syscall = nr;
36+
}
37+
3138
static inline void syscall_rollback(struct task_struct *task,
3239
struct pt_regs *regs)
3340
{

include/asm-generic/syscall.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,20 @@ struct pt_regs;
3737
*/
3838
int syscall_get_nr(struct task_struct *task, struct pt_regs *regs);
3939

40+
/**
41+
* syscall_set_nr - change the system call a task is executing
42+
* @task: task of interest, must be blocked
43+
* @regs: task_pt_regs() of @task
44+
* @nr: system call number
45+
*
46+
* Changes the system call number @task is about to execute.
47+
*
48+
* It's only valid to call this when @task is stopped for tracing on
49+
* entry to a system call, due to %SYSCALL_WORK_SYSCALL_TRACE or
50+
* %SYSCALL_WORK_SYSCALL_AUDIT.
51+
*/
52+
void syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr);
53+
4054
/**
4155
* syscall_rollback - roll back registers after an aborted system call
4256
* @task: task of interest, must be in system call exit tracing

0 commit comments

Comments
 (0)