entry: Consolidate and rework syscall entry handling
Subsystems (30)
Thomas Gleixner
maintainercover entry: Consolidate and rework syscall entry handling
Sorry for the long CC list, but this is a treewide change.
Michal recently posted a RFC patch to separate the potential syscall number modifications in syscall_enter_user_mode_work() from the information whether the syscall should be processed and the return value modified:
https://lore.kernel.org/lkml/[email protected]
The existing logic is:
arch_syscall()
regs->result = -ENOSYS; syscallnr = syscall_enter_from_user_mode(regs, syscall); if (syscallnr != -1L) regs->result = invoke_syscall(regs, syscall;
syscall_enter_from_user_mode() invokes ptrace, seccomp and tracing/BPF/Probes. All of them can modify the syscall number.
ptrace and seccomp explicitly set the syscall number to -1L to indicate that the syscall invocation needs to be skipped and the result has not to be modified as it might have been modified by ptrace or seccomp. The tracer/BPF/Probes mechanism can modify the syscall number as well and relies implicitly on the -1L logic.
This can obviously not be differentiated from a syscall invocation where userspace provided -1 as syscall number.
The general agreement of the discussion was that the current mechanism, while functionally correct is non-intuitive and something like Michals proposal would make that code clearer and easier to handle on the architecture side:
arch_syscall()
regs->result = -ENOSYS; if (syscall_enter_from_user_mode(regs, &syscall)) regs->result = invoke_syscall(regs, syscall;
That discussion made me look deeper into the related code and as usual there were a lot of other things to discover.
1) Stack randomization
add_random_kstack_offset() can only be invoked after enter_from_user_mode() established proper state as it calls into instrumentable code.
PowerPC got that wrong and the other architectures either invoke it after enter_from_user_mode() or after syscall_enter_from_user_mode().
The latter is suboptimal as the randomization takes place after all the user mode entry work. Aside of that add_random_kstack_offset() uses get/put_cpu_var(), which makes it usable in preemptible code, but when invoked in the interrupt disabled region that's pointless overhead.
2) As discussed in the above thread just changing the function signature of syscall_enter_from_user_mode[_work]() so they take a pointer argument for the syscall and then return 0 on success is not really intuitive either. Aside of that this breaks the implicit assumption of the tracer when setting the syscall number to -1.
3) The x86 entry code has some historically accumulated oddities
The following series addresses this by:
1) Providing new [syscall_]enter_from_user_mode() variants, which include stack randomization and utilize a new add_random_kstack_offset_irqsoff() variant, which avoids the get/put_cpu_var() overhead and converting all usage sites over
2) Picking up Jinjie's seccomp patch from:
https://lore.kernel.org/lkml/[email protected]
and addressing the feedback (renaming the seccomp functions)
3) Making the ptrace and tracer related functions return a boolean value to indicate syscall permission
4) Addressing the x86 oddities
5) Converting the tree over to the new scheme
With that all architectures using the generic syscall entry code follow the same scheme, apply stack randomization at the correct and earliest possible place and skip syscall processing depending on the boolean return value of syscall_enter_from_user_mode[_work]().
There should be no functional changes, at least there are none intended.
The resulting text size for the syscall entry code on x8664 is slightly smaller than before these changes.
Testing syscall heavy workloads and micro benchmarks shows a small performance gain for the general rework, but the last patch, which changes the logic to be more understandable has no measurable impact in either direction.
The series applies on Linus tree and is also available from git:
git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git entry-rework-v1
Thanks,
tglx
--- Documentation/core-api/entry.rst | 33 +++++--- arch/alpha/kernel/ptrace.c | 4 - arch/arc/kernel/ptrace.c | 2 arch/arm/kernel/ptrace.c | 4 - arch/arm64/kernel/ptrace.c | 4 - arch/csky/kernel/ptrace.c | 4 - arch/hexagon/kernel/traps.c | 2 arch/loongarch/kernel/syscall.c | 17 +--- arch/m68k/kernel/ptrace.c | 4 - arch/microblaze/kernel/ptrace.c | 2 arch/mips/kernel/ptrace.c | 4 - arch/nios2/kernel/ptrace.c | 2 arch/openrisc/kernel/ptrace.c | 2 arch/parisc/kernel/ptrace.c | 12 +-- arch/powerpc/kernel/syscall.c | 5 - arch/riscv/kernel/traps.c | 14 +-- arch/s390/kernel/syscall.c | 11 +- arch/sh/kernel/ptrace_32.c | 4 - arch/sparc/kernel/ptrace_32.c | 2 arch/sparc/kernel/ptrace_64.c | 2 arch/um/kernel/ptrace.c | 2 arch/um/kernel/skas/syscall.c | 2 arch/x86/entry/syscall_32.c | 70 +++++++------------ arch/x86/entry/syscall_64.c | 61 ++++++---------- arch/x86/entry/vsyscall/vsyscall_64.c | 14 +-- arch/x86/include/asm/entry-common.h | 1 arch/x86/include/asm/syscall.h | 10 -- arch/xtensa/kernel/ptrace.c | 5 - include/asm-generic/syscall.h | 4 - include/linux/entry-common.h | 125 ++++++++++++++++++++-------------- include/linux/irq-entry-common.h | 6 - include/linux/ptrace.h | 13 +-- include/linux/randomize_kstack.h | 19 +++++ include/linux/seccomp.h | 12 +-- kernel/entry/syscall-common.c | 7 + kernel/seccomp.c | 35 ++++----- 36 files changed, 264 insertions(+), 256 deletions(-)
Thomas Gleixner
maintainerPATCH 1/18 powerpc: Move stack randomization after syscall_enter_from_user_mode()
add_random_kstack_offset() is invoked before syscall_enter_from_user_mode() establishes state. That's wrong because add_random_kstack_offset() calls into instrumentable code.
Move it after syscall_enter_from_user_mode() to ensure that state is correctly established.
--- arch/powerpc/kernel/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kernel/syscall.c +1 -1
@@ -19,8 +19,8 @@ notrace long system_call_exception(struclong ret;syscall_fn f; -add_random_kstack_offset (); r0 =syscall_enter_from_user_mode (regs, r0); +add_random_kstack_offset ();if (unlikely (r0 >= NR_syscalls)) {if (unlikely (trap_is_unsupported_scv (regs))) {
Re: [patch 01/18] powerpc: Move stack randomization after syscall_enter_from_user_mode()
Quoted 3 lines · Thomas Gleixner
add_random_kstack_offset()is invoked beforesyscall_enter_from_user_mode()establishes state. That's wrong becauseadd_random_kstack_offset()calls into instrumentable code.
Thanks for fixing that.
Quoted 16 lines
Move it after
syscall_enter_from_user_mode()to ensure that state is correctly established.Signed-off-by Thomas Gleixner <[email protected]>Cc Michael Ellerman <[email protected]>Cc Shrikanth Hegde <[email protected]>--- arch/powerpc/kernel/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kernel/syscall.c notrace long system_call_exception(struc · line 26
Quoted 9 lines
arch/powerpc/kernel/syscall.c +1
-1@@ -19,8 +19,8 @@ notrace long system_call_exception(struclong ret;syscall_fn f; -add_random_kstack_offset (); r0 =syscall_enter_from_user_mode (regs, r0); +add_random_kstack_offset ();if (unlikely (r0 >= NR_syscalls)) {if (unlikely (trap_is_unsupported_scv (regs))) {
Re: [patch 01/18] powerpc: Move stack randomization after syscall_enter_from_user_mode()
In reply to Thomas GleixnerQuoted 24 lines · Thomas Gleixner
add_random_kstack_offset()is invoked beforesyscall_enter_from_user_mode()establishes state. That's wrong becauseadd_random_kstack_offset()calls into instrumentable code.Move it after
syscall_enter_from_user_mode()to ensure that state is correctly established.Signed-off-by Thomas Gleixner <[email protected]>Cc Michael Ellerman <[email protected]>Cc Shrikanth Hegde <[email protected]>---
arch/powerpc/kernel/syscall.c | 2 +-1 file changed, 1 insertion(+), 1 deletion(-)arch/powerpc/kernel/syscall.c +0
-0@@ -19,8 +19,8 @@ notrace long system_call_exception(struc long ret; syscall_fn f;arch/powerpc/kernel/syscall.c +0
-1-add_random_kstack_offset ();r0 =
syscall_enter_from_user_mode(regs, r0);arch/powerpc/kernel/syscall.c +1
-0+add_random_kstack_offset ();
Quoted 3 lines
if (unlikely(r0 >= NR_syscalls)) {
if (unlikely(trap_is_unsupported_scv(regs))) {
Re: [patch 01/18] powerpc: Move stack randomization after syscall_enter_from_user_mode()
In reply to Thomas GleixnerQuoted 18 lines · Thomas Gleixner
add_random_kstack_offset()is invoked beforesyscall_enter_from_user_mode()establishes state. That's wrong becauseadd_random_kstack_offset()calls into instrumentable code.Move it after
syscall_enter_from_user_mode()to ensure that state is correctly established.Signed-off-by Thomas Gleixner <[email protected]>Cc Michael Ellerman <[email protected]>Cc Shrikanth Hegde <[email protected]>--- arch/powerpc/kernel/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kernel/syscall.c notrace long system_call_exception(struc · line 23
Quoted 6 lines
arch/powerpc/kernel/syscall.c +1
-1@@ -19,8 +19,8 @@ notrace long system_call_exception(struclong ret;syscall_fn f; -add_random_kstack_offset (); r0 =syscall_enter_from_user_mode (regs, r0); +add_random_kstack_offset ();
Quoted 4 lines
arch/powerpc/kernel/syscall.c +0
-0if (unlikely (r0 >= NR_syscalls)) {if (unlikely (trap_is_unsupported_scv (regs))) {
Re: [patch 01/18] powerpc: Move stack randomization after syscall_enter_from_user_mode()
In reply to Thomas GleixnerQuoted 19 lines · Thomas Gleixner
add_random_kstack_offset()is invoked beforesyscall_enter_from_user_mode()establishes state. That's wrong becauseadd_random_kstack_offset()calls into instrumentable code.Move it after
syscall_enter_from_user_mode()to ensure that state is correctly established.Signed-off-by Thomas Gleixner <[email protected]>Cc Michael Ellerman <[email protected]>Cc Shrikanth Hegde <[email protected]>--- arch/powerpc/kernel/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kernel/syscall.c notrace long system_call_exception(struc · line 26
Quoted 9 lines
arch/powerpc/kernel/syscall.c +1
-1@@ -19,8 +19,8 @@ notrace long system_call_exception(struclong ret;syscall_fn f; -add_random_kstack_offset (); r0 =syscall_enter_from_user_mode (regs, r0); +add_random_kstack_offset ();if (unlikely (r0 >= NR_syscalls)) {if (unlikely (trap_is_unsupported_scv (regs))) {
Re: [patch 01/18] powerpc: Move stack randomization after syscall_enter_from_user_mode()
In reply to Thomas GleixnerQuoted 11 lines · Thomas Gleixner
add_random_kstack_offset()is invoked beforesyscall_enter_from_user_mode()establishes state. That's wrong becauseadd_random_kstack_offset()calls into instrumentable code.Move it after
syscall_enter_from_user_mode()to ensure that state is correctly established.Signed-off-by Thomas Gleixner <[email protected]>Cc Michael Ellerman <[email protected]>Cc Shrikanth Hegde <[email protected]>
Thanks for fixing this.
[...]
[tip: core/entry] powerpc: Move stack randomization after syscall_enter_from_user_mode()
In reply to Thomas GleixnerThe following commit has been merged into the core/entry branch of tip:
The following commit has been merged into the core/entry branch of tip:
Commit-ID: 89d163dd9dacb028773244dba0a2c86f3a6b74b7 Gitweb: https://git.kernel.org/tip/89d163dd9dacb028773244dba0a2c86f3a6b74b7 Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 07 Jul 2026 21:05:58 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Sun, 12 Jul 2026 12:38:00 +02:00
powerpc: Move stack randomization after syscall_enter_from_user_mode()
add_random_kstack_offset() is invoked before syscall_enter_from_user_mode() establishes state. That's wrong because add_random_kstack_offset() calls into instrumentable code.
Move it after syscall_enter_from_user_mode() to ensure that state is correctly established.
--- arch/powerpc/kernel/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kernel/syscall.c +1 -1
@@ -19,8 +19,8 @@ notrace long system_call_exception(struct pt_regs *regs, unsigned long r0)long ret;syscall_fn f; -add_random_kstack_offset (); r0 =syscall_enter_from_user_mode (regs, r0); +add_random_kstack_offset ();if (unlikely (r0 >= NR_syscalls)) {if (unlikely (trap_is_unsupported_scv (regs))) {
Thomas Gleixner
maintainerPATCH 2/18 randomize_kstack: Provide add_random_kstack_offset_irqsoff()
In reply to Thomas Gleixneradd_random_kstack_offset() uses get/put_cpu_var() which is pointless overhead when it is invoked from low level entry code with interrupts disabled.
Provide a irqsoff() variant, which avoids that.
--- include/linux/randomize_kstack.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
include/linux/randomize_kstack.h +19 -0
@@ -77,8 +77,27 @@ static __always_inline u32 get_kstack_of } \ } while (0) +/** +* add_random_kstack_offset_irqsoff - Increase stack utilization by a random offset. +* +* This should be used in the syscall entry path after user registers have been +* stored to the stack. Interrupts must be still disabled. + */ +#define add_random_kstack_offset_irqsoff () \ +do { \ + lockdep_assert_irqs_disabled(); \ + if (static_branch_maybe(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, \ + &randomize_kstack_offset)) { \ + u32 offset = prandom_u32_state(raw_cpu_ptr(&kstack_rnd_state)); \ + u8 *ptr = __kstack_alloca(KSTACK_OFFSET_MAX(offset)); \ +/* Keep allocation even after "ptr" loses scope. */ \ + asmvolatile ("" ::"r" (ptr) :"memory" ); \ + } \ +} while (0) +#else /* CONFIG_RANDOMIZE_KSTACK_OFFSET */ #define add_random_kstack_offset () do { } while (0) +#define add_random_kstack_offset_irqsoff () do { } while (0)#endif /* CONFIG_RANDOMIZE_KSTACK_OFFSET */ #endif
Re: [patch 02/18] randomize_kstack: Provide add_random_kstack_offset_irqsoff()
Quoted 36 lines · Thomas Gleixner
add_random_kstack_offset()uses get/put_cpu_var() which is pointless overhead when it is invoked from low level entry code with interrupts disabled.Provide a
irqsoff()variant, which avoids that.Signed-off-by Thomas Gleixner <[email protected]>Cc Kees Cook <[email protected]>---
include/linux/randomize_kstack.h | 19 +++++++++++++++++++1 file changed, 19 insertions(+)include/linux/randomize_kstack.h +0
-0@@ -77,8 +77,27 @@ static __always_inline u32 get_kstack_of } \ } while (0)include/linux/randomize_kstack.h +18
-0+/** +* add_random_kstack_offset_irqsoff - Increase stack utilization by a random offset. +* +* This should be used in the syscall entry path after user registers have been +* stored to the stack. Interrupts must be still disabled. +*/ +#define add_random_kstack_offset_irqsoff () \ +do { \ + lockdep_assert_irqs_disabled(); \ + if (static_branch_maybe(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, \ + &randomize_kstack_offset)) { \ + u32 offset = prandom_u32_state(raw_cpu_ptr(&kstack_rnd_state)); \ + u8 *ptr = __kstack_alloca(KSTACK_OFFSET_MAX(offset)); \ +/* Keep allocation even after "ptr" loses scope. */ \ + asmvolatile ("" ::"r" (ptr) :"memory" ); \ + } \ +} while (0) +
Quoted 6 lines
#else /*
CONFIG_RANDOMIZE_KSTACK_OFFSET*/
#defineadd_random_kstack_offset()do { } while (0)
+#defineadd_random_kstack_offset_irqsoff()do { } while (0)
#endif /*CONFIG_RANDOMIZE_KSTACK_OFFSET*/
#endif
Re: [patch 02/18] randomize_kstack: Provide add_random_kstack_offset_irqsoff()
In reply to Thomas GleixnerQuoted 25 lines · Thomas Gleixner
add_random_kstack_offset()uses get/put_cpu_var() which is pointless overhead when it is invoked from low level entry code with interrupts disabled.Provide a
irqsoff()variant, which avoids that.Signed-off-by Thomas Gleixner <[email protected]>Cc Kees Cook <[email protected]>--- include/linux/randomize_kstack.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)include/linux/randomize_kstack.h +7
-0@@ -77,8 +77,27 @@ static __always_inline u32 get_kstack_of } \ }while (0 ) +/** +* add_random_kstack_offset_irqsoff - Increase stack utilization by a random offset. +* +* This should be used in the syscall entry path after user registers have been +* stored to the stack. Interrupts must be still disabled. +*/ +#define add_random_kstack_offset_irqsoff() \
include/linux/randomize_kstack.h static __always_inline u32 get_kstack_of · line 96
Quoted 10 lines
include/linux/randomize_kstack.h +10
-0+do { \ +lockdep_assert_irqs_disabled (); \ +if (static_branch_maybe (CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT , \ + &randomize_kstack_offset)) { \ +u32 offset =prandom_u32_state (raw_cpu_ptr (&kstack_rnd_state)); \ +u8 *ptr =__kstack_alloca (KSTACK_OFFSET_MAX (offset)); \ +/* Keep allocation even after "ptr" loses scope. */ \ + asmvolatile ("" ::"r" (ptr) :"memory" ); \ + } \ +}while (0 )
Or can we avoid these repetitions and reuse the same code?
Quoted 8 lines
include/linux/randomize_kstack.h +2
-0+#else /* CONFIG_RANDOMIZE_KSTACK_OFFSET */ #define add_random_kstack_offset () do { } while (0) +#define add_random_kstack_offset_irqsoff () do { } while (0)#endif /* CONFIG_RANDOMIZE_KSTACK_OFFSET */ #endif
Re: [patch 02/18] randomize_kstack: Provide add_random_kstack_offset_irqsoff()
In reply to Thomas GleixnerQuoted 7 lines · Thomas Gleixner
add_random_kstack_offset()uses get/put_cpu_var() which is pointless overhead when it is invoked from low level entry code with interrupts disabled.Provide a
irqsoff()variant, which avoids that.Signed-off-by Thomas Gleixner <[email protected]>
Seems good. I don't think macro'izing the interior is worth it since both cases are very short, with only the lockdep and raw bits changed.
-Kees
Signature · 1 line
Kees Cook
Re: [patch 02/18] randomize_kstack: Provide add_random_kstack_offset_irqsoff()
In reply to Thomas GleixnerQuoted 33 lines · Thomas Gleixner
add_random_kstack_offset()uses get/put_cpu_var() which is pointless overhead when it is invoked from low level entry code with interrupts disabled.Provide a
irqsoff()variant, which avoids that.Signed-off-by Thomas Gleixner <[email protected]>Cc Kees Cook <[email protected]>--- include/linux/randomize_kstack.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)include/linux/randomize_kstack.h +14
-0@@ -77,8 +77,27 @@ static __always_inline u32 get_kstack_of } \ }while (0 ) +/** +* add_random_kstack_offset_irqsoff - Increase stack utilization by a random offset. +* +* This should be used in the syscall entry path after user registers have been +* stored to the stack. Interrupts must be still disabled. + */ +#define add_random_kstack_offset_irqsoff () \ +do { \ + lockdep_assert_irqs_disabled(); \ + if (static_branch_maybe(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, \ + &randomize_kstack_offset)) { \ + u32 offset = prandom_u32_state(raw_cpu_ptr(&kstack_rnd_state)); \ + u8 *ptr = __kstack_alloca(KSTACK_OFFSET_MAX(offset)); \ +/* Keep allocation even after "ptr" loses scope. */ \
include/linux/randomize_kstack.h static __always_inline u32 get_kstack_of · line 103
Quoted 10 lines
include/linux/randomize_kstack.h +5
-0+ asmvolatile ("" ::"r" (ptr) :"memory" ); \ + } \ +} while (0) +#else /* CONFIG_RANDOMIZE_KSTACK_OFFSET */ #define add_random_kstack_offset () do { } while (0) +#define add_random_kstack_offset_irqsoff () do { } while (0)#endif /* CONFIG_RANDOMIZE_KSTACK_OFFSET */ #endif
LGTM.
Quoted 5 lines
_______________________________________________
linux-snps-arc mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-snps-arc
[tip: core/entry] randomize_kstack: Provide add_random_kstack_offset_irqsoff()
In reply to Thomas GleixnerThe following commit has been merged into the core/entry branch of tip:
The following commit has been merged into the core/entry branch of tip:
Commit-ID: 0b9a3057530cc1c3f87ce2ab9d1278164e81990f Gitweb: https://git.kernel.org/tip/0b9a3057530cc1c3f87ce2ab9d1278164e81990f Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 07 Jul 2026 21:06:02 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Sun, 12 Jul 2026 12:38:00 +02:00
randomize_kstack: Provide add_random_kstack_offset_irqsoff()
add_random_kstack_offset() uses get/put_cpu_var() which is pointless overhead when it is invoked from low level entry code with interrupts disabled.
Provide a irqsoff() variant, which avoids that.
--- include/linux/randomize_kstack.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
include/linux/randomize_kstack.h +19 -0
@@ -77,8 +77,27 @@ static __always_inline u32 get_kstack_offset(void) } \ } while (0) +/** +* add_random_kstack_offset_irqsoff - Increase stack utilization by a random offset. +* +* This should be used in the syscall entry path after user registers have been +* stored to the stack. Interrupts must be still disabled. + */ +#define add_random_kstack_offset_irqsoff () \ +do { \ + lockdep_assert_irqs_disabled(); \ + if (static_branch_maybe(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, \ + &randomize_kstack_offset)) { \ + u32 offset = prandom_u32_state(raw_cpu_ptr(&kstack_rnd_state)); \ + u8 *ptr = __kstack_alloca(KSTACK_OFFSET_MAX(offset)); \ +/* Keep allocation even after "ptr" loses scope. */ \ + asmvolatile ("" ::"r" (ptr) :"memory" ); \ + } \ +} while (0) +#else /* CONFIG_RANDOMIZE_KSTACK_OFFSET */ #define add_random_kstack_offset () do { } while (0) +#define add_random_kstack_offset_irqsoff () do { } while (0)#endif /* CONFIG_RANDOMIZE_KSTACK_OFFSET */ #endif
Thomas Gleixner
maintainerPATCH 3/18 entry: Provide [syscall_]enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerRandomizing the syscall stack can only happen after state is established via enter_from_user_mode() or syscall_enter_from_user_mode(). The earlier it happens the better.
Provide two new macros to consolidate that:
- enter_from_user_mode_randomize_stack()
enter_from_user_mode(); add_random_kstack_offset_irqsoff();
- syscall_enter_from_user_mode_randomize_stack()
enter_from_user_mode_randomize_stack(); syscall_enter_from_user_mode_work();
to reduce boiler plate code.
Those are macros and not inline functions as the latter would limit the stack randomization scope to the inline function itself.
--- include/linux/entry-common.h | 56 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)
include/linux/entry-common.h +56 -0
@@ -6,6 +6,7 @@#include <linux/irq-entry-common.h> #include <linux/livepatch.h> #include <linux/ptrace.h> +#include <linux/randomize_kstack.h> #include <linux/resume_user_mode.h> #include <linux/seccomp.h> #include <linux/sched.h>
@@ -150,6 +151,61 @@ static __always_inline long syscall_ente }/** +* enter_from_user_mode_randomize_stack - Establish state and add stack randomization +* before invoking syscall_enter_from_user_mode_work() +* @regs: Pointer to currents pt_regs +* +* Invoked from architecture specific syscall entry code with interrupts +* disabled. The calling code has to be non-instrumentable. When the function +* returns all state is correct, interrupts are still disabled and the +* subsequent functions can be instrumented. +* +* Implemented as a macro so that the stack randomization is effective +* throughout the function in which it is invoked. An inline would only make it +* effective in the scope of the inline function. +*/ +#define enter_from_user_mode_randomize_stack (regs) \ +do { \ + enter_from_user_mode(regs); \ + instrumentation_begin(); \ + add_random_kstack_offset_irqsoff(); \ + instrumentation_end(); \ +} while (0) + +/** +* syscall_enter_from_user_mode_randomize_stack - Establish state and check and handle work +* before invoking a syscall +* @regs: Pointer to currents pt_regs +* @syscall: The syscall number +* +* Invoked from architecture specific syscall entry code with interrupts +* disabled. The calling code has to be non-instrumentable. When the +* function returns all state is correct, interrupts are enabled and the +* subsequent functions can be instrumented. +* +* This is the combination of enter_from_user_mode_randomize_stack() and +* syscall_enter_from_user_mode_work() to be used when there is no +* architecture specific work to be done between the two. +* +* Returns: The original or a modified syscall number. See +* syscall_enter_from_user_mode_work() for further explanation. +* +* Implemented as a macro to make stack randomization effective in the calling +* scope. +*/ +#define syscall_enter_from_user_mode_randomize_stack (regs, syscall) \ +({ \ + enter_from_user_mode_randomize_stack(regs); \ + \ + instrumentation_begin(); \ + local_irq_enable(); \ + long _ret = syscall_enter_from_user_mode_work(regs, syscall); \ + instrumentation_end(); \ + \ + _ret; \ +}) + +/** * syscall_enter_from_user_mode - Establish state and check and handle work * before invoking a syscall * @regs: Pointer to currents pt_regs
Re: [patch 03/18] entry: Provide [syscall_]enter_from_user_mode_randomize_stack()
Quoted 36 lines · Thomas Gleixner
Randomizing the syscall stack can only happen after state is established via
enter_from_user_mode()orsyscall_enter_from_user_mode(). The earlier it happens the better.Provide two new macros to consolidate that:
-
enter_from_user_mode_randomize_stack()enter_from_user_mode(); add_random_kstack_offset_irqsoff();-
syscall_enter_from_user_mode_randomize_stack()enter_from_user_mode_randomize_stack(); syscall_enter_from_user_mode_work();
to reduce boiler plate code.Those are macros and not inline functions as the latter would limit the stack randomization scope to the inline function itself.
Signed-off-by Thomas Gleixner <[email protected]>---
include/linux/entry-common.h | 56 +++++++++++++++++++++++++++++++++++++++++++1 file changed, 56 insertions(+)include/linux/entry-common.h +1
-0@@ -6,6 +6,7 @@ #include <linux/irq-entry-common.h> #include <linux/livepatch.h> #include <linux/ptrace.h> +#include <linux/randomize_kstack.h> #include <linux/resume_user_mode.h> #include <linux/seccomp.h> #include <linux/sched.h>@@ -150,6 +151,61 @@ static __always_inline long syscall_ente }
Quoted 5 lines
/**
+ *enter_from_user_mode_randomize_stack- Establish state and add stack randomization
+ * before invokingsyscall_enter_from_user_mode_work()
+ * @regs: Pointer to currentspt_regs
^^^^^^^^
Nit: current
Quoted 12 lines
+ *
+ * Invoked from architecture specific syscall entry code with interrupts
+ * disabled. The calling code has to be non-instrumentable. When the function
+ * returns all state is correct, interrupts are still disabled and the
+ * subsequent functions can be instrumented.
+ *
+ * Implemented as a macro so that the stack randomization is effective
+ * throughout the function in which it is invoked. An inline would only make it
+ * effective in the scope of the inline function.
+ */include/linux/entry-common.h +2
-0+#define enter_from_user_mode_randomize_stack (regs) \ +do { \
include/linux/entry-common.h static __always_inline long syscall_ente · line 178
Quoted 10 lines
include/linux/entry-common.h +10
-0+enter_from_user_mode (regs); \ +instrumentation_begin (); \ +add_random_kstack_offset_irqsoff (); \ +instrumentation_end (); \ +}while (0 ) + +/** +* syscall_enter_from_user_mode_randomize_stack - Establish state and check and handle work +* before invoking a syscall +* @regs: Pointer to currents pt_regs
^^^^^^^^
Same here.
Quoted 30 lines
+ * @syscall: The syscall number
+ *
+ * Invoked from architecture specific syscall entry code with interrupts
+ * disabled. The calling code has to be non-instrumentable. When the
+ * function returns all state is correct, interrupts are enabled and the
+ * subsequent functions can be instrumented.
+ *
+ * This is the combination ofenter_from_user_mode_randomize_stack()and
+ *syscall_enter_from_user_mode_work()to be used when there is no
+ * architecture specific work to be done between the two.
+ *
+ * Returns: The original or a modified syscall number. See
+ *syscall_enter_from_user_mode_work()for further explanation.
+ *
+ * Implemented as a macro to make stack randomization effective in the calling
+ * scope.
+ */include/linux/entry-common.h +13
-0+#define syscall_enter_from_user_mode_randomize_stack (regs, syscall) \ +({ \ + enter_from_user_mode_randomize_stack(regs); \ + \ + instrumentation_begin(); \ + local_irq_enable(); \ + long _ret = syscall_enter_from_user_mode_work(regs, syscall); \ + instrumentation_end(); \ + \ + _ret; \ +}) + +/**
Quoted 3 lines
*
syscall_enter_from_user_mode- Establish state and check and handle work
* before invoking a syscall
* @regs: Pointer to currentspt_regs
With the above nits,
Re: [patch 03/18] entry: Provide [syscall_]enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 81 lines · Thomas Gleixner
Randomizing the syscall stack can only happen after state is established via
enter_from_user_mode()orsyscall_enter_from_user_mode(). The earlier it happens the better.Provide two new macros to consolidate that:
-
enter_from_user_mode_randomize_stack()enter_from_user_mode(); add_random_kstack_offset_irqsoff();-
syscall_enter_from_user_mode_randomize_stack()enter_from_user_mode_randomize_stack(); syscall_enter_from_user_mode_work();to reduce boiler plate code.
Those are macros and not inline functions as the latter would limit the stack randomization scope to the inline function itself.
Signed-off-by Thomas Gleixner <[email protected]>--- include/linux/entry-common.h | 56 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)include/linux/entry-common.h +44
-0@@ -6,6 +6,7 @@#include <linux/irq-entry-common.h> #include <linux/livepatch.h> #include <linux/ptrace.h> +#include <linux/randomize_kstack.h> #include <linux/resume_user_mode.h> #include <linux/seccomp.h> #include <linux/sched.h> @@ -150,6 +151,61 @@ static __always_inline long syscall_ente }/** +* enter_from_user_mode_randomize_stack - Establish state and add stack randomization +* before invoking syscall_enter_from_user_mode_work() +* @regs: Pointer to currents pt_regs +* +* Invoked from architecture specific syscall entry code with interrupts +* disabled. The calling code has to be non-instrumentable. When the function +* returns all state is correct, interrupts are still disabled and the +* subsequent functions can be instrumented. +* +* Implemented as a macro so that the stack randomization is effective +* throughout the function in which it is invoked. An inline would only make it +* effective in the scope of the inline function. +*/ +#define enter_from_user_mode_randomize_stack (regs) \ +do { \ + enter_from_user_mode(regs); \ + instrumentation_begin(); \ + add_random_kstack_offset_irqsoff(); \ + instrumentation_end(); \ +} while (0) + +/** +* syscall_enter_from_user_mode_randomize_stack - Establish state and check and handle work +* before invoking a syscall +* @regs: Pointer to currents pt_regs +* @syscall: The syscall number +* +* Invoked from architecture specific syscall entry code with interrupts +* disabled. The calling code has to be non-instrumentable. When the +* function returns all state is correct, interrupts are enabled and the +* subsequent functions can be instrumented. +* +* This is the combination of enter_from_user_mode_randomize_stack() and +* syscall_enter_from_user_mode_work() to be used when there is no +* architecture specific work to be done between the two. +* +* Returns: The original or a modified syscall number. See +* syscall_enter_from_user_mode_work() for further explanation. +* +* Implemented as a macro to make stack randomization effective in the calling +* scope. +*/ +#define syscall_enter_from_user_mode_randomize_stack (regs, syscall) \
include/linux/entry-common.h static __always_inline long syscall_ente · line 206
Quoted 10 lines
include/linux/entry-common.h +10
-0+({ \ +enter_from_user_mode_randomize_stack (regs); \ + \ +instrumentation_begin (); \ +local_irq_enable (); \ +long _ret =syscall_enter_from_user_mode_work (regs, syscall); \ +instrumentation_end (); \ + \ + _ret; \ +})
Quoted 6 lines
include/linux/entry-common.h +2
-0+ +/** * syscall_enter_from_user_mode - Establish state and check and handle work * before invoking a syscall * @regs: Pointer to currents pt_regs
Re: [patch 03/18] entry: Provide [syscall_]enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 48 lines · Thomas Gleixner
Randomizing the syscall stack can only happen after state is established via
enter_from_user_mode()orsyscall_enter_from_user_mode(). The earlier it happens the better.Provide two new macros to consolidate that:
-
enter_from_user_mode_randomize_stack()enter_from_user_mode(); add_random_kstack_offset_irqsoff();-
syscall_enter_from_user_mode_randomize_stack()enter_from_user_mode_randomize_stack(); syscall_enter_from_user_mode_work();to reduce boiler plate code.
Those are macros and not inline functions as the latter would limit the stack randomization scope to the inline function itself.
Signed-off-by Thomas Gleixner <[email protected]>--- include/linux/entry-common.h | 56 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)include/linux/entry-common.h +11
-0@@ -6,6 +6,7 @@#include <linux/irq-entry-common.h> #include <linux/livepatch.h> #include <linux/ptrace.h> +#include <linux/randomize_kstack.h> #include <linux/resume_user_mode.h> #include <linux/seccomp.h> #include <linux/sched.h> @@ -150,6 +151,61 @@ static __always_inline long syscall_ente }/** +* enter_from_user_mode_randomize_stack - Establish state and add stack randomization +* before invoking syscall_enter_from_user_mode_work() +* @regs: Pointer to currents pt_regs +* +* Invoked from architecture specific syscall entry code with interrupts +* disabled. The calling code has to be non-instrumentable. When the function +* returns all state is correct, interrupts are still disabled and the +* subsequent functions can be instrumented. +* +* Implemented as a macro so that the stack randomization is effective
include/linux/entry-common.h static __always_inline long syscall_ente · line 173
Quoted 10 lines
include/linux/entry-common.h +10
-0+* throughout the function in which it is invoked. An inline would only make it +* effective in the scope of the inline function. +*/ +#define enter_from_user_mode_randomize_stack (regs) \ +do { \ + enter_from_user_mode(regs); \ + instrumentation_begin(); \ + add_random_kstack_offset_irqsoff(); \ + instrumentation_end(); \ +} while (0)
Perhaps this new function can also be reused when the ARM64 is switched to the generic entry as the irq also disabled now.
arch/arm64/kernel/entry-common.c +0 -0
@@ -64,7 +64,7 @@ static void noinstr arm64_exit_to_kernel_mode(struct
pt_regs *regs,
static __always_inline void arm64_syscall_enter_from_user_mode(structpt_regs *regs)
{
- enter_from_user_mode(regs);
+ enter_from_user_mode_randomize_stack(regs);
mte_disable_tco_entry(current);
sme_enter_from_user_mode();}
arch/arm64/kernel/syscall.c +0 -1
@@ -6,7 +6,6 @@#include <linux/errno.h> #include <linux/nospec.h> #include <linux/ptrace.h> -#include <linux/randomize_kstack.h> #include <linux/syscalls.h> #include <asm/debug-monitors.h>
@@ -42,8 +41,6 @@ static void invoke_syscall(struct pt_regs *regs,
unsigned int scno,
{
long ret;- add_random_kstack_offset();
-
if (likely(scno < sc_nr)) {
syscall_fn_t syscall_fn;
syscall_fn = syscall_table[array_index_nospec(scno, sc_nr)];Quoted 39 lines
include/linux/entry-common.h +35
-0+ +/** +* syscall_enter_from_user_mode_randomize_stack - Establish state and check and handle work +* before invoking a syscall +* @regs: Pointer to currents pt_regs +* @syscall: The syscall number +* +* Invoked from architecture specific syscall entry code with interrupts +* disabled. The calling code has to be non-instrumentable. When the +* function returns all state is correct, interrupts are enabled and the +* subsequent functions can be instrumented. +* +* This is the combination of enter_from_user_mode_randomize_stack() and +* syscall_enter_from_user_mode_work() to be used when there is no +* architecture specific work to be done between the two. +* +* Returns: The original or a modified syscall number. See +* syscall_enter_from_user_mode_work() for further explanation. +* +* Implemented as a macro to make stack randomization effective in the calling +* scope. +*/ +#define syscall_enter_from_user_mode_randomize_stack (regs, syscall) \ +({ \ + enter_from_user_mode_randomize_stack(regs); \ + \ + instrumentation_begin(); \ + local_irq_enable(); \ + long _ret = syscall_enter_from_user_mode_work(regs, syscall); \ + instrumentation_end(); \ + \ + _ret; \ +}) + +/** * syscall_enter_from_user_mode - Establish state and check and handle work * before invoking a syscall * @regs: Pointer to currents pt_regs
Re: [patch 03/18] entry: Provide [syscall_]enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 16 lines · Thomas Gleixner
Randomizing the syscall stack can only happen after state is established via
enter_from_user_mode()orsyscall_enter_from_user_mode(). The earlier it happens the better.Provide two new macros to consolidate that:
- enter_from_user_mode_randomize_stack() enter_from_user_mode(); add_random_kstack_offset_irqsoff(); - syscall_enter_from_user_mode_randomize_stack() enter_from_user_mode_randomize_stack(); syscall_enter_from_user_mode_work();to reduce boiler plate code.
Quoted 7 lines
Those are macros and not inline functions as the latter would limit the stack randomization scope to the inline function itself.
Signed-off-by Thomas Gleixner <[email protected]>--- include/linux/entry-common.h | 56 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)
Re: [patch 03/18] entry: Provide [syscall_]enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 87 lines · Thomas Gleixner
Randomizing the syscall stack can only happen after state is established via
enter_from_user_mode()orsyscall_enter_from_user_mode(). The earlier it happens the better.Provide two new macros to consolidate that:
-
enter_from_user_mode_randomize_stack()enter_from_user_mode(); add_random_kstack_offset_irqsoff();-
syscall_enter_from_user_mode_randomize_stack()enter_from_user_mode_randomize_stack(); syscall_enter_from_user_mode_work();to reduce boiler plate code.
Those are macros and not inline functions as the latter would limit the stack randomization scope to the inline function itself.
Signed-off-by Thomas Gleixner <[email protected]>--- include/linux/entry-common.h | 56 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)include/linux/entry-common.h +49
-0@@ -6,6 +6,7 @@#include <linux/irq-entry-common.h> #include <linux/livepatch.h> #include <linux/ptrace.h> +#include <linux/randomize_kstack.h> #include <linux/resume_user_mode.h> #include <linux/seccomp.h> #include <linux/sched.h> @@ -150,6 +151,61 @@ static __always_inline long syscall_ente }/** +* enter_from_user_mode_randomize_stack - Establish state and add stack randomization +* before invoking syscall_enter_from_user_mode_work() +* @regs: Pointer to currents pt_regs +* +* Invoked from architecture specific syscall entry code with interrupts +* disabled. The calling code has to be non-instrumentable. When the function +* returns all state is correct, interrupts are still disabled and the +* subsequent functions can be instrumented. +* +* Implemented as a macro so that the stack randomization is effective +* throughout the function in which it is invoked. An inline would only make it +* effective in the scope of the inline function. +*/ +#define enter_from_user_mode_randomize_stack (regs) \ +do { \ + enter_from_user_mode(regs); \ + instrumentation_begin(); \ + add_random_kstack_offset_irqsoff(); \ + instrumentation_end(); \ +} while (0) + +/** +* syscall_enter_from_user_mode_randomize_stack - Establish state and check and handle work +* before invoking a syscall +* @regs: Pointer to currents pt_regs +* @syscall: The syscall number +* +* Invoked from architecture specific syscall entry code with interrupts +* disabled. The calling code has to be non-instrumentable. When the +* function returns all state is correct, interrupts are enabled and the +* subsequent functions can be instrumented. +* +* This is the combination of enter_from_user_mode_randomize_stack() and +* syscall_enter_from_user_mode_work() to be used when there is no +* architecture specific work to be done between the two. +* +* Returns: The original or a modified syscall number. See +* syscall_enter_from_user_mode_work() for further explanation. +* +* Implemented as a macro to make stack randomization effective in the calling +* scope. +*/ +#define syscall_enter_from_user_mode_randomize_stack (regs, syscall) \ +({ \ + enter_from_user_mode_randomize_stack(regs); \ + \ + instrumentation_begin(); \ + local_irq_enable(); \
include/linux/entry-common.h static __always_inline long syscall_ente · line 211
Quoted 10 lines
include/linux/entry-common.h +7
-0+long _ret =syscall_enter_from_user_mode_work (regs, syscall); \ +instrumentation_end (); \ + \ + _ret; \ +}) + +/** * syscall_enter_from_user_mode - Establish state and check and handle work * before invoking a syscall * @regs: Pointer to currents pt_regs
Quoted 5 lines
_______________________________________________
linux-snps-arc mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-snps-arc
[tip: core/entry] entry: Provide [syscall_]enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerThe following commit has been merged into the core/entry branch of tip:
The following commit has been merged into the core/entry branch of tip:
Commit-ID: 855c103f86275a55eba115cabb86eb84f8236933 Gitweb: https://git.kernel.org/tip/855c103f86275a55eba115cabb86eb84f8236933 Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 07 Jul 2026 21:06:07 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Sun, 12 Jul 2026 12:38:01 +02:00
entry: Provide [syscall_]enter_from_user_mode_randomize_stack()
Randomizing the syscall stack can only happen after state is established via enter_from_user_mode() or syscall_enter_from_user_mode(). The earlier it happens the better.
Provide two new macros to consolidate that:
- enter_from_user_mode_randomize_stack()
enter_from_user_mode(); add_random_kstack_offset_irqsoff();
- syscall_enter_from_user_mode_randomize_stack()
enter_from_user_mode_randomize_stack(); syscall_enter_from_user_mode_work();
to reduce boiler plate code.
Those are macros and not inline functions as the latter would limit the stack randomization scope to the inline function itself.
--- include/linux/entry-common.h | 56 +++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+)
include/linux/entry-common.h +56 -0
@@ -6,6 +6,7 @@#include <linux/irq-entry-common.h> #include <linux/livepatch.h> #include <linux/ptrace.h> +#include <linux/randomize_kstack.h> #include <linux/resume_user_mode.h> #include <linux/seccomp.h> #include <linux/sched.h>
@@ -150,6 +151,61 @@ static __always_inline long syscall_enter_from_user_mode_work(struct pt_regs *re }/** +* enter_from_user_mode_randomize_stack - Establish state and add stack randomization +* before invoking syscall_enter_from_user_mode_work() +* @regs: Pointer to currents pt_regs +* +* Invoked from architecture specific syscall entry code with interrupts +* disabled. The calling code has to be non-instrumentable. When the function +* returns all state is correct, interrupts are still disabled and the +* subsequent functions can be instrumented. +* +* Implemented as a macro so that the stack randomization is effective +* throughout the function in which it is invoked. An inline would only make it +* effective in the scope of the inline function. +*/ +#define enter_from_user_mode_randomize_stack (regs) \ +do { \ + enter_from_user_mode(regs); \ + instrumentation_begin(); \ + add_random_kstack_offset_irqsoff(); \ + instrumentation_end(); \ +} while (0) + +/** +* syscall_enter_from_user_mode_randomize_stack - Establish state and check and handle work +* before invoking a syscall +* @regs: Pointer to currents pt_regs +* @syscall: The syscall number +* +* Invoked from architecture specific syscall entry code with interrupts +* disabled. The calling code has to be non-instrumentable. When the +* function returns all state is correct, interrupts are enabled and the +* subsequent functions can be instrumented. +* +* This is the combination of enter_from_user_mode_randomize_stack() and +* syscall_enter_from_user_mode_work() to be used when there is no +* architecture specific work to be done between the two. +* +* Returns: The original or a modified syscall number. See +* syscall_enter_from_user_mode_work() for further explanation. +* +* Implemented as a macro to make stack randomization effective in the calling +* scope. +*/ +#define syscall_enter_from_user_mode_randomize_stack (regs, syscall) \ +({ \ + enter_from_user_mode_randomize_stack(regs); \ + \ + instrumentation_begin(); \ + local_irq_enable(); \ + long _ret = syscall_enter_from_user_mode_work(regs, syscall); \ + instrumentation_end(); \ + \ + _ret; \ +}) + +/** * syscall_enter_from_user_mode - Establish state and check and handle work * before invoking a syscall * @regs: Pointer to currents pt_regs
H. Peter Anvin
reviewerRe: [patch 03/18] entry: Provide [syscall_]enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 10 lines · Thomas Gleixner
Randomizing the syscall stack can only happen after state is established via
enter_from_user_mode()orsyscall_enter_from_user_mode(). The earlier it happens the better.Provide two new macros to consolidate that:
-
enter_from_user_mode_randomize_stack()enter_from_user_mode(); add_random_kstack_offset_irqsoff();
Quoted 9 lines
-
syscall_enter_from_user_mode_randomize_stack()enter_from_user_mode_randomize_stack(); syscall_enter_from_user_mode_work();to reduce boiler plate code.
Those are macros and not inline functions as the latter would limit the stack randomization scope to the inline function itself.
Not directly related to this patchset, but still:
Can anyone *please* find out what the actual security requirements are for the syscall randomization offset?
The original checkin, 39218ff4c625 ("stack: Optionally randomize kernel stack offset each syscall") indicates that it is fundamental that the stack offset is applied *after* pt_regs pushing, but that isn't documented anywhere in the kernel sources as far as I can tell.
However, I have also come to understand that there are further, undocumented constraints; at least at one point I was told that "the offset should not be stored in memory while running in the kernel", which seems more than a bit odd.
This matters, because it creates a data dependency on exit. The original checkin does call out that RDTSC timing is inappropriate if the user could control it, but using a hardware CSPRNG like RDRAND (or its equivalent for other architectures) would be feasible if it isn't in the critical path. If an RDRAND - store sequence can be executed on entry, *after* the stack adjustment, then the high latency of RDRAND can hopefully be very effectively hidden by an OO CPU.
Incidentally, in case you are wondering "why doesn't each core get a dedicated CSPRNG and hardware randomness generator, to avoid high latency", the answer is pretty simple: a hardware random number source, regardless of the specifics of the design, almost by definition violates the hardware design rules of any digital design; after all, the design rules are designed to *eliminate* noise (making the circuit behave as closely as physically possible to a realization of the abstract digital circuit), whereas the very goal of a HWRNG source is to *extract and amplify* quantum thermal noise. This means that considerable chip area is consumed by a "keep-out zone", a designated "no man's land" keeping the digital logic away from the noise source. This keep-out zone is typically much, much larger than the noise source itself.
-hpa
Thomas Gleixner
maintainerRe: [patch 03/18] entry: Provide [syscall_]enter_from_user_mode_randomize_stack()
Quoted 11 lines · H. Peter Anvin
Can anyone *please* find out what the actual security requirements are for the syscall randomization offset?
The original checkin,
39218ff4c625("stack: Optionally randomize kernel stack offset each syscall") indicates that it is fundamental that the stack offset is applied *after*pt_regspushing, but that isn't documented anywhere in the kernel sources as far as I can tell.However, I have also come to understand that there are further, undocumented constraints; at least at one point I was told that "the offset should not be stored in memory while running in the kernel", which seems more than a bit odd.
This thread has the initial discussions about it with more explanations:
Thanks,
tglx
Thomas Gleixner
maintainerPATCH 4/18 loongarch/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas Gleixnersyscall_enter_from_user_mode_randomize_stack() replaces syscall_enter_from_user_mode() and the subsequent invocation of add_random_kstack_offset().
The advantage is that it applies the stack randomization right after enter_from_user_mode() and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.
No functional change.
--- arch/loongarch/kernel/syscall.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
arch/loongarch/kernel/syscall.c +1 -4
@@ -11,7 +11,6 @@#include <linux/linkage.h> #include <linux/nospec.h> #include <linux/objtool.h> -#include <linux/randomize_kstack.h> #include <linux/syscalls.h> #include <linux/unistd.h>
@@ -70,9 +69,7 @@ void noinstr __no_stack_protector do_sys regs->orig_a0 = regs->regs[4 ]; regs->regs[4 ] = -ENOSYS ; - nr =syscall_enter_from_user_mode (regs, nr); - -add_random_kstack_offset (); + nr =syscall_enter_from_user_mode_randomize_stack (regs, nr);if (nr < NR_syscalls) { syscall_fn = sys_call_table[array_index_nospec (nr, NR_syscalls)];
Re: [patch 04/18] loongarch/syscall: Use syscall_enter_from_user_mode_randomize_stack()
Quoted 35 lines · Thomas Gleixner
syscall_enter_from_user_mode_randomize_stack()replacessyscall_enter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset().The advantage is that it applies the stack randomization right after
enter_from_user_mode()and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Huacai Chen <[email protected]>---
arch/loongarch/kernel/syscall.c | 5 +----1 file changed, 1 insertion(+), 4 deletions(-)arch/loongarch/kernel/syscall.c +0
-1@@ -11,7 +11,6 @@ #include <linux/linkage.h> #include <linux/nospec.h> #include <linux/objtool.h> -#include <linux/randomize_kstack.h> #include <linux/syscalls.h> #include <linux/unistd.h>arch/loongarch/kernel/syscall.c +0
-0@@ -70,9 +69,7 @@ void noinstr __no_stack_protector do_sys regs->orig_a0 = regs->regs[4]; regs->regs[4] = -ENOSYS;arch/loongarch/kernel/syscall.c +1
-3- nr =syscall_enter_from_user_mode (regs, nr); - -add_random_kstack_offset (); + nr =syscall_enter_from_user_mode_randomize_stack (regs, nr);
Quoted 3 lines
if (nr <NR_syscalls) {
syscall_fn= sys_call_table[array_index_nospec(nr,NR_syscalls)];
Re: [patch 04/18] loongarch/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 28 lines · Thomas Gleixner
syscall_enter_from_user_mode_randomize_stack()replacessyscall_enter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset().The advantage is that it applies the stack randomization right after
enter_from_user_mode()and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Huacai Chen <[email protected]>--- arch/loongarch/kernel/syscall.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)arch/loongarch/kernel/syscall.c +0
-1@@ -11,7 +11,6 @@#include <linux/linkage.h> #include <linux/nospec.h> #include <linux/objtool.h> -#include <linux/randomize_kstack.h> #include <linux/syscalls.h> #include <linux/unistd.h>
arch/loongarch/kernel/syscall.c void noinstr __no_stack_protector do_sys · line 72
Quoted 7 lines
arch/loongarch/kernel/syscall.c +1
-3@@ -70,9 +69,7 @@ void noinstr __no_stack_protector do_sys regs->orig_a0 = regs->regs[4 ]; regs->regs[4 ] = -ENOSYS ; - nr =syscall_enter_from_user_mode (regs, nr); - -add_random_kstack_offset (); + nr =syscall_enter_from_user_mode_randomize_stack (regs, nr);
Quoted 4 lines
arch/loongarch/kernel/syscall.c +0
-0if (nr < NR_syscalls) { syscall_fn = sys_call_table[array_index_nospec (nr, NR_syscalls)];
Re: [patch 04/18] loongarch/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 8 lines · Thomas Gleixner
syscall_enter_from_user_mode_randomize_stack()replacessyscall_enter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset().The advantage is that it applies the stack randomization right after
enter_from_user_mode()and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.
Quoted 8 lines
No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Huacai Chen <[email protected]>--- arch/loongarch/kernel/syscall.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
Re: [patch 04/18] loongarch/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 30 lines · Thomas Gleixner
syscall_enter_from_user_mode_randomize_stack()replacessyscall_enter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset().The advantage is that it applies the stack randomization right after
enter_from_user_mode()and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Huacai Chen <[email protected]>--- arch/loongarch/kernel/syscall.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)arch/loongarch/kernel/syscall.c +0
-1@@ -11,7 +11,6 @@#include <linux/linkage.h> #include <linux/nospec.h> #include <linux/objtool.h> -#include <linux/randomize_kstack.h> #include <linux/syscalls.h> #include <linux/unistd.h>
arch/loongarch/kernel/syscall.c void noinstr __no_stack_protector do_sys · line 75
Quoted 10 lines
arch/loongarch/kernel/syscall.c +1
-3@@ -70,9 +69,7 @@ void noinstr __no_stack_protector do_sys regs->orig_a0 = regs->regs[4 ]; regs->regs[4 ] = -ENOSYS ; - nr =syscall_enter_from_user_mode (regs, nr); - -add_random_kstack_offset (); + nr =syscall_enter_from_user_mode_randomize_stack (regs, nr);if (nr < NR_syscalls) { syscall_fn = sys_call_table[array_index_nospec (nr, NR_syscalls)];
Quoted 4 lines
_______________________________________________
linux-snps-arc mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-snps-arc
[tip: core/entry] loongarch/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerThe following commit has been merged into the core/entry branch of tip:
The following commit has been merged into the core/entry branch of tip:
Commit-ID: 7892c5a22a4e11d1ed3590c04ff73f047c0ce453 Gitweb: https://git.kernel.org/tip/7892c5a22a4e11d1ed3590c04ff73f047c0ce453 Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 07 Jul 2026 21:06:11 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Sun, 12 Jul 2026 12:38:01 +02:00
loongarch/syscall: Use syscall_enter_from_user_mode_randomize_stack()
syscall_enter_from_user_mode_randomize_stack() replaces syscall_enter_from_user_mode() and the subsequent invocation of add_random_kstack_offset().
The advantage is that it applies the stack randomization right after enter_from_user_mode() and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.
No functional change.
--- arch/loongarch/kernel/syscall.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
arch/loongarch/kernel/syscall.c +1 -4
@@ -11,7 +11,6 @@#include <linux/linkage.h> #include <linux/nospec.h> #include <linux/objtool.h> -#include <linux/randomize_kstack.h> #include <linux/syscalls.h> #include <linux/unistd.h>
@@ -70,9 +69,7 @@ void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) regs->orig_a0 = regs->regs[4 ]; regs->regs[4 ] = -ENOSYS ; - nr =syscall_enter_from_user_mode (regs, nr); - -add_random_kstack_offset (); + nr =syscall_enter_from_user_mode_randomize_stack (regs, nr);if (nr < NR_syscalls) { syscall_fn = sys_call_table[array_index_nospec (nr, NR_syscalls)];
Thomas Gleixner
maintainerPATCH 5/18 powerpc/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas Gleixnersyscall_enter_from_user_mode_randomize_stack() replaces syscall_enter_from_user_mode() and the subsequent invocation of add_random_kstack_offset().
The advantage is that it applies the stack randomization right after enter_from_user_mode() and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.
No functional change.
--- arch/powerpc/kernel/syscall.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
arch/powerpc/kernel/syscall.c +1 -3
@@ -2,7 +2,6 @@#include <linux/compat.h> #include <linux/context_tracking.h> -#include <linux/randomize_kstack.h> #include <linux/entry-common.h> #include <asm/interrupt.h>
@@ -19,8 +18,7 @@ notrace long system_call_exception(struclong ret;syscall_fn f; - r0 =syscall_enter_from_user_mode (regs, r0); -add_random_kstack_offset (); + r0 =syscall_enter_from_user_mode_randomize_stack (regs, r0);if (unlikely (r0 >= NR_syscalls)) {if (unlikely (trap_is_unsupported_scv (regs))) {
Re: [patch 05/18] powerpc/syscall: Use syscall_enter_from_user_mode_randomize_stack()
Quoted 35 lines · Thomas Gleixner
syscall_enter_from_user_mode_randomize_stack()replacessyscall_enter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset().The advantage is that it applies the stack randomization right after
enter_from_user_mode()and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Michael Ellerman <[email protected]>Cc Shrikanth Hegde <[email protected]>---
arch/powerpc/kernel/syscall.c | 4 +---1 file changed, 1 insertion(+), 3 deletions(-)arch/powerpc/kernel/syscall.c +0
-0@@ -2,7 +2,6 @@
#include <linux/compat.h>
#include <linux/context_tracking.h>
-#include <linux/randomize_kstack.h>
#include <linux/entry-common.h>
#include <asm/interrupt.h>arch/powerpc/kernel/syscall.c +0
-0@@ -19,8 +18,7 @@ notrace long system_call_exception(struc long ret; syscall_fn f;arch/powerpc/kernel/syscall.c +1
-2- r0 =syscall_enter_from_user_mode (regs, r0); -add_random_kstack_offset (); + r0 =syscall_enter_from_user_mode_randomize_stack (regs, r0);
Quoted 3 lines
if (unlikely(r0 >= NR_syscalls)) {
if (unlikely(trap_is_unsupported_scv(regs))) {
Re: [patch 05/18] powerpc/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 29 lines · Thomas Gleixner
syscall_enter_from_user_mode_randomize_stack()replacessyscall_enter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset().The advantage is that it applies the stack randomization right after
enter_from_user_mode()and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Michael Ellerman <[email protected]>Cc Shrikanth Hegde <[email protected]>--- arch/powerpc/kernel/syscall.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)arch/powerpc/kernel/syscall.c +0
-1@@ -2,7 +2,6 @@#include <linux/compat.h> #include <linux/context_tracking.h> -#include <linux/randomize_kstack.h> #include <linux/entry-common.h> #include <asm/interrupt.h>
arch/powerpc/kernel/syscall.c notrace long system_call_exception(struc · line 21
Quoted 6 lines
arch/powerpc/kernel/syscall.c +1
-2@@ -19,8 +18,7 @@ notrace long system_call_exception(struclong ret;syscall_fn f; - r0 =syscall_enter_from_user_mode (regs, r0); -add_random_kstack_offset (); + r0 =syscall_enter_from_user_mode_randomize_stack (regs, r0);
Quoted 4 lines
arch/powerpc/kernel/syscall.c +0
-0if (unlikely (r0 >= NR_syscalls)) {if (unlikely (trap_is_unsupported_scv (regs))) {
Re: [patch 05/18] powerpc/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 10 lines · Thomas Gleixner
syscall_enter_from_user_mode_randomize_stack()replacessyscall_enter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset().The advantage is that it applies the stack randomization right after
enter_from_user_mode()and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.No functional change.
Quoted 7 lines
Signed-off-by Thomas Gleixner <[email protected]>Cc Michael Ellerman <[email protected]>Cc Shrikanth Hegde <[email protected]>--- arch/powerpc/kernel/syscall.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
Re: [patch 05/18] powerpc/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 30 lines · Thomas Gleixner
syscall_enter_from_user_mode_randomize_stack()replacessyscall_enter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset().The advantage is that it applies the stack randomization right after
enter_from_user_mode()and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Michael Ellerman <[email protected]>Cc Shrikanth Hegde <[email protected]>--- arch/powerpc/kernel/syscall.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)arch/powerpc/kernel/syscall.c +0
-1@@ -2,7 +2,6 @@#include <linux/compat.h> #include <linux/context_tracking.h> -#include <linux/randomize_kstack.h> #include <linux/entry-common.h> #include <asm/interrupt.h>
arch/powerpc/kernel/syscall.c notrace long system_call_exception(struc · line 24
Quoted 9 lines
arch/powerpc/kernel/syscall.c +1
-2@@ -19,8 +18,7 @@ notrace long system_call_exception(struclong ret;syscall_fn f; - r0 =syscall_enter_from_user_mode (regs, r0); -add_random_kstack_offset (); + r0 =syscall_enter_from_user_mode_randomize_stack (regs, r0);if (unlikely (r0 >= NR_syscalls)) {if (unlikely (trap_is_unsupported_scv (regs))) {
[tip: core/entry] powerpc/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerThe following commit has been merged into the core/entry branch of tip:
The following commit has been merged into the core/entry branch of tip:
Commit-ID: 3b2b9c0198bbcf077f201cd693a0efc597d05405 Gitweb: https://git.kernel.org/tip/3b2b9c0198bbcf077f201cd693a0efc597d05405 Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 07 Jul 2026 21:06:15 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Sun, 12 Jul 2026 12:38:01 +02:00
powerpc/syscall: Use syscall_enter_from_user_mode_randomize_stack()
syscall_enter_from_user_mode_randomize_stack() replaces syscall_enter_from_user_mode() and the subsequent invocation of add_random_kstack_offset().
The advantage is that it applies the stack randomization right after enter_from_user_mode() and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.
No functional change.
--- arch/powerpc/kernel/syscall.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
arch/powerpc/kernel/syscall.c +1 -3
@@ -2,7 +2,6 @@#include <linux/compat.h> #include <linux/context_tracking.h> -#include <linux/randomize_kstack.h> #include <linux/entry-common.h> #include <asm/interrupt.h>
@@ -19,8 +18,7 @@ notrace long system_call_exception(struct pt_regs *regs, unsigned long r0)long ret;syscall_fn f; - r0 =syscall_enter_from_user_mode (regs, r0); -add_random_kstack_offset (); + r0 =syscall_enter_from_user_mode_randomize_stack (regs, r0);if (unlikely (r0 >= NR_syscalls)) {if (unlikely (trap_is_unsupported_scv (regs))) {
Thomas Gleixner
maintainerPATCH 6/18 riscv/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas Gleixnersyscall_enter_from_user_mode_randomize_stack() replaces syscall_enter_from_user_mode() and the subsequent invocation of add_random_kstack_offset().
The advantage is that it applies the stack randomization right after enter_from_user_mode() and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.
No functional change.
--- arch/riscv/kernel/traps.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
arch/riscv/kernel/traps.c +1 -4
@@ -7,7 +7,6 @@#include <linux/kernel.h> #include <linux/init.h> #include <linux/irqflags.h> -#include <linux/randomize_kstack.h> #include <linux/sched.h> #include <linux/sched/debug.h> #include <linux/sched/signal.h>
@@ -333,9 +332,7 @@ void do_trap_ecall_u(struct pt_regs *regriscv_v_vstate_discard (regs); - syscall =syscall_enter_from_user_mode (regs, syscall); - -add_random_kstack_offset (); + syscall =syscall_enter_from_user_mode_randomize_stack (regs, syscall);if (syscall >=0 && syscall < NR_syscalls) { syscall =array_index_nospec (syscall, NR_syscalls);
Re: [patch 06/18] riscv/syscall: Use syscall_enter_from_user_mode_randomize_stack()
Quoted 36 lines · Thomas Gleixner
syscall_enter_from_user_mode_randomize_stack()replacessyscall_enter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset().The advantage is that it applies the stack randomization right after
enter_from_user_mode()and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Paul Walmsley <[email protected]>Cc Palmer Dabbelt <[email protected]>---
arch/riscv/kernel/traps.c | 5 +----1 file changed, 1 insertion(+), 4 deletions(-)arch/riscv/kernel/traps.c +0
-1@@ -7,7 +7,6 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/irqflags.h> -#include <linux/randomize_kstack.h> #include <linux/sched.h> #include <linux/sched/debug.h> #include <linux/sched/signal.h>@@ -333,9 +332,7 @@ void do_trap_ecall_u(struct pt_regs *reg
riscv_v_vstate_discard(regs);arch/riscv/kernel/traps.c +1
-3- syscall =syscall_enter_from_user_mode (regs, syscall); - -add_random_kstack_offset (); + syscall =syscall_enter_from_user_mode_randomize_stack (regs, syscall);
Quoted 3 lines
if (syscall >= 0 && syscall <NR_syscalls) { syscall =array_index_nospec(syscall, NR_syscalls);
Re: [patch 06/18] riscv/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 29 lines · Thomas Gleixner
syscall_enter_from_user_mode_randomize_stack()replacessyscall_enter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset().The advantage is that it applies the stack randomization right after
enter_from_user_mode()and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Paul Walmsley <[email protected]>Cc Palmer Dabbelt <[email protected]>--- arch/riscv/kernel/traps.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)arch/riscv/kernel/traps.c +0
-1@@ -7,7 +7,6 @@#include <linux/kernel.h> #include <linux/init.h> #include <linux/irqflags.h> -#include <linux/randomize_kstack.h> #include <linux/sched.h> #include <linux/sched/debug.h> #include <linux/sched/signal.h>
arch/riscv/kernel/traps.c void do_trap_ecall_u(struct pt_regs *reg · line 335
Quoted 7 lines
arch/riscv/kernel/traps.c +1
-3@@ -333,9 +332,7 @@ void do_trap_ecall_u(struct pt_regs *regriscv_v_vstate_discard (regs); - syscall =syscall_enter_from_user_mode (regs, syscall); - -add_random_kstack_offset (); + syscall =syscall_enter_from_user_mode_randomize_stack (regs, syscall);
Quoted 4 lines
arch/riscv/kernel/traps.c +0
-0if (syscall >=0 && syscall < NR_syscalls) { syscall =array_index_nospec (syscall, NR_syscalls);
Re: [patch 06/18] riscv/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 10 lines · Thomas Gleixner
syscall_enter_from_user_mode_randomize_stack()replacessyscall_enter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset().The advantage is that it applies the stack randomization right after
enter_from_user_mode()and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.No functional change.
Quoted 7 lines
Signed-off-by Thomas Gleixner <[email protected]>Cc Paul Walmsley <[email protected]>Cc Palmer Dabbelt <[email protected]>--- arch/riscv/kernel/traps.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
Re: [patch 06/18] riscv/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 30 lines · Thomas Gleixner
syscall_enter_from_user_mode_randomize_stack()replacessyscall_enter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset().The advantage is that it applies the stack randomization right after
enter_from_user_mode()and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Paul Walmsley <[email protected]>Cc Palmer Dabbelt <[email protected]>--- arch/riscv/kernel/traps.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)arch/riscv/kernel/traps.c +0
-1@@ -7,7 +7,6 @@#include <linux/kernel.h> #include <linux/init.h> #include <linux/irqflags.h> -#include <linux/randomize_kstack.h> #include <linux/sched.h> #include <linux/sched/debug.h> #include <linux/sched/signal.h>
arch/riscv/kernel/traps.c void do_trap_ecall_u(struct pt_regs *reg · line 338
Quoted 10 lines
arch/riscv/kernel/traps.c +1
-3@@ -333,9 +332,7 @@ void do_trap_ecall_u(struct pt_regs *regriscv_v_vstate_discard (regs); - syscall =syscall_enter_from_user_mode (regs, syscall); - -add_random_kstack_offset (); + syscall =syscall_enter_from_user_mode_randomize_stack (regs, syscall);if (syscall >=0 && syscall < NR_syscalls) { syscall =array_index_nospec (syscall, NR_syscalls);
[tip: core/entry] riscv/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerThe following commit has been merged into the core/entry branch of tip:
The following commit has been merged into the core/entry branch of tip:
Commit-ID: d023abfbc4dca9ad9c9928b5b5a38b1628ee1a5d Gitweb: https://git.kernel.org/tip/d023abfbc4dca9ad9c9928b5b5a38b1628ee1a5d Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 07 Jul 2026 21:06:19 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Sun, 12 Jul 2026 12:38:01 +02:00
riscv/syscall: Use syscall_enter_from_user_mode_randomize_stack()
syscall_enter_from_user_mode_randomize_stack() replaces syscall_enter_from_user_mode() and the subsequent invocation of add_random_kstack_offset().
The advantage is that it applies the stack randomization right after enter_from_user_mode() and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.
No functional change.
--- arch/riscv/kernel/traps.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
arch/riscv/kernel/traps.c +1 -4
@@ -7,7 +7,6 @@#include <linux/kernel.h> #include <linux/init.h> #include <linux/irqflags.h> -#include <linux/randomize_kstack.h> #include <linux/sched.h> #include <linux/sched/debug.h> #include <linux/sched/signal.h>
@@ -333,9 +332,7 @@ void do_trap_ecall_u(struct pt_regs *regs)riscv_v_vstate_discard (regs); - syscall =syscall_enter_from_user_mode (regs, syscall); - -add_random_kstack_offset (); + syscall =syscall_enter_from_user_mode_randomize_stack (regs, syscall);if (syscall >=0 && syscall < NR_syscalls) { syscall =array_index_nospec (syscall, NR_syscalls);
Re: [patch 06/18] riscv/syscall: Use syscall_enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 30 lines · Thomas Gleixner
syscall_enter_from_user_mode_randomize_stack()replacessyscall_enter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset().The advantage is that it applies the stack randomization right after
enter_from_user_mode()and thereby avoids the overhead of get/put_cpu_var() as that code is invoked with interrupts disabled.No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Paul Walmsley <[email protected]>Cc Palmer Dabbelt <[email protected]>--- arch/riscv/kernel/traps.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)arch/riscv/kernel/traps.c +0
-1@@ -7,7 +7,6 @@#include <linux/kernel.h> #include <linux/init.h> #include <linux/irqflags.h> -#include <linux/randomize_kstack.h> #include <linux/sched.h> #include <linux/sched/debug.h> #include <linux/sched/signal.h>
arch/riscv/kernel/traps.c void do_trap_ecall_u(struct pt_regs *reg · line 335
Quoted 7 lines
arch/riscv/kernel/traps.c +1
-3@@ -333,9 +332,7 @@ void do_trap_ecall_u(struct pt_regs *regriscv_v_vstate_discard (regs); - syscall =syscall_enter_from_user_mode (regs, syscall); - -add_random_kstack_offset (); + syscall =syscall_enter_from_user_mode_randomize_stack (regs, syscall);
Signature · 2 lines
Best Regards Guo Ren
Thomas Gleixner
maintainerPATCH 7/18 s390/syscall: Use enter_from_user_mode_randomize_stack()
In reply to Thomas Gleixnerenter_from_user_mode_randomize_stack() replaces enter_from_user_mode() and the subsequent invocation of add_random_kstack_offset_irqsoff().
As a bonus this avoids the overhead of get/put_cpu_var() in add_random_kstack_offset().
No functional change.
--- arch/s390/kernel/syscall.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/s390/kernel/syscall.c +2 -2
@@ -97,8 +97,8 @@ void noinstr __do_syscall(struct pt_regs {unsigned long nr; -enter_from_user_mode (regs); -add_random_kstack_offset (); +enter_from_user_mode_randomize_stack (regs); + regs->psw =get_lowcore ()->svc_old_psw; regs->int_code =get_lowcore ()->svc_int_code;update_timer_sys ();
Re: [patch 07/18] s390/syscall: Use enter_from_user_mode_randomize_stack()
Quoted 18 lines · Thomas Gleixner
enter_from_user_mode_randomize_stack()replacesenter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset_irqsoff().As a bonus this avoids the overhead of get/put_cpu_var() in
add_random_kstack_offset().No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Sven Schnelle <[email protected]>--- arch/s390/kernel/syscall.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/s390/kernel/syscall.c void noinstr __do_syscall(struct pt_regs · line 104
Quoted 10 lines
arch/s390/kernel/syscall.c +2
-2@@ -97,8 +97,8 @@ void noinstr __do_syscall(struct pt_regs {unsigned long nr; -enter_from_user_mode (regs); -add_random_kstack_offset (); +enter_from_user_mode_randomize_stack (regs); + regs->psw =get_lowcore ()->svc_old_psw; regs->int_code =get_lowcore ()->svc_int_code;update_timer_sys ();
Re: [patch 07/18] s390/syscall: Use enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 25 lines · Thomas Gleixner
enter_from_user_mode_randomize_stack()replacesenter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset_irqsoff().As a bonus this avoids the overhead of get/put_cpu_var() in
add_random_kstack_offset().No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Sven Schnelle <[email protected]>---
arch/s390/kernel/syscall.c | 4 ++--1 file changed, 2 insertions(+), 2 deletions(-)arch/s390/kernel/syscall.c +0
-0@@ -97,8 +97,8 @@ void noinstr __do_syscall(struct pt_regs { unsigned long nr;arch/s390/kernel/syscall.c +2
-2-enter_from_user_mode (regs); -add_random_kstack_offset (); +enter_from_user_mode_randomize_stack (regs); +
Quoted 3 lines
regs->psw= get_lowcore()->svc_old_psw;regs->int_code= get_lowcore()->svc_int_code;update_timer_sys();
Re: [patch 07/18] s390/syscall: Use enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 18 lines · Thomas Gleixner
enter_from_user_mode_randomize_stack()replacesenter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset_irqsoff().As a bonus this avoids the overhead of get/put_cpu_var() in
add_random_kstack_offset().No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Sven Schnelle <[email protected]>--- arch/s390/kernel/syscall.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/s390/kernel/syscall.c void noinstr __do_syscall(struct pt_regs · line 100
Quoted 6 lines
arch/s390/kernel/syscall.c +1
-2@@ -97,8 +97,8 @@ void noinstr __do_syscall(struct pt_regs {unsigned long nr; -enter_from_user_mode (regs); -add_random_kstack_offset (); +enter_from_user_mode_randomize_stack (regs);
Quoted 5 lines
arch/s390/kernel/syscall.c +1
-0+ regs->psw =get_lowcore ()->svc_old_psw; regs->int_code =get_lowcore ()->svc_int_code;update_timer_sys ();
Re: [patch 07/18] s390/syscall: Use enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 18 lines · Thomas Gleixner
enter_from_user_mode_randomize_stack()replacesenter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset_irqsoff().As a bonus this avoids the overhead of get/put_cpu_var() in
add_random_kstack_offset().No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Sven Schnelle <[email protected]>--- arch/s390/kernel/syscall.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/s390/kernel/syscall.c void noinstr __do_syscall(struct pt_regs · line 100
Quoted 6 lines
arch/s390/kernel/syscall.c +1
-2@@ -97,8 +97,8 @@ void noinstr __do_syscall(struct pt_regs {unsigned long nr; -enter_from_user_mode (regs); -add_random_kstack_offset (); +enter_from_user_mode_randomize_stack (regs);
The #include <linux/randomize_kstack.h> can be removed.
Quoted 5 lines
arch/s390/kernel/syscall.c +1
-0+ regs->psw =get_lowcore ()->svc_old_psw; regs->int_code =get_lowcore ()->svc_int_code;update_timer_sys ();
Philippe Mathieu-Daudé
Reviewed-byRe: [patch 07/18] s390/syscall: Use enter_from_user_mode_randomize_stack()
Quoted 24 lines · Jinjie Ruan
Quoted 21 lines · Thomas Gleixner
enter_from_user_mode_randomize_stack()replacesenter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset_irqsoff().As a bonus this avoids the overhead of get/put_cpu_var() in
add_random_kstack_offset().No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Sven Schnelle <[email protected]>--- arch/s390/kernel/syscall.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)arch/s390/kernel/syscall.c +0
-0@@ -97,8 +97,8 @@ void noinstr __do_syscall(struct pt_regs {unsigned long nr;
Quoted 5 lines
arch/s390/kernel/syscall.c void noinstr __do_syscall(struct pt_regs · line 100
Quoted 3 lines
arch/s390/kernel/syscall.c +1
-2-enter_from_user_mode (regs); -add_random_kstack_offset (); +enter_from_user_mode_randomize_stack (regs);The #include <
linux/randomize_kstack.h> can be removed.
Re: [patch 07/18] s390/syscall: Use enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 19 lines · Thomas Gleixner
enter_from_user_mode_randomize_stack()replacesenter_from_user_mode()and the subsequent invocation ofadd_random_kstack_offset_irqsoff().As a bonus this avoids the overhead of get/put_cpu_var() in
add_random_kstack_offset().No functional change.
Signed-off-by Thomas Gleixner <[email protected]>Cc Sven Schnelle <[email protected]>--- arch/s390/kernel/syscall.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/s390/kernel/syscall.c void noinstr __do_syscall(struct pt_regs · line 104
Quoted 10 lines
arch/s390/kernel/syscall.c +2
-2@@ -97,8 +97,8 @@ void noinstr __do_syscall(struct pt_regs {unsigned long nr; -enter_from_user_mode (regs); -add_random_kstack_offset (); +enter_from_user_mode_randomize_stack (regs); + regs->psw =get_lowcore ()->svc_old_psw; regs->int_code =get_lowcore ()->svc_int_code;update_timer_sys ();
[tip: core/entry] s390/syscall: Use enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerThe following commit has been merged into the core/entry branch of tip:
The following commit has been merged into the core/entry branch of tip:
Commit-ID: 05a194d8bd005e0887a1e089bbbbd2e1a641638f Gitweb: https://git.kernel.org/tip/05a194d8bd005e0887a1e089bbbbd2e1a641638f Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 07 Jul 2026 21:06:23 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Sun, 12 Jul 2026 12:38:01 +02:00
s390/syscall: Use enter_from_user_mode_randomize_stack()
enter_from_user_mode_randomize_stack() replaces enter_from_user_mode() and the subsequent invocation of add_random_kstack_offset_irqsoff().
As a bonus this avoids the overhead of get/put_cpu_var() in add_random_kstack_offset().
No functional change.
--- arch/s390/kernel/syscall.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/s390/kernel/syscall.c +2 -2
@@ -97,8 +97,8 @@ void noinstr __do_syscall(struct pt_regs *regs, int per_trap) {unsigned long nr; -enter_from_user_mode (regs); -add_random_kstack_offset (); +enter_from_user_mode_randomize_stack (regs); + regs->psw =get_lowcore ()->svc_old_psw; regs->int_code =get_lowcore ()->svc_int_code;update_timer_sys ();
Thomas Gleixner
maintainerPATCH 8/18 x86/syscall: Use [syscall_]enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerThese functions integrate the stack randomization.
syscall_enter_from_user_mode_randomize_stack() has the advantage that the randomization happens early right after enter_from_user_mode().
In both cases also the overhead of get/put_cpu_var() in add_random_kstack_offset() is avoided.
No functional change.
--- arch/x86/entry/syscall_32.c | 19 +++++-------------- arch/x86/entry/syscall_64.c | 3 +-- arch/x86/include/asm/entry-common.h | 1 - 3 files changed, 6 insertions(+), 17 deletions(-)
arch/x86/entry/syscall_32.c +5 -14
@@ -142,10 +142,9 @@ static __always_inline bool int80_is_ext* int80_is_external() below which calls into the APIC driver. * Identical for soft and external interrupts. */ -enter_from_user_mode (regs); +enter_from_user_mode_randomize_stack (regs);instrumentation_begin (); -add_random_kstack_offset ();/* Validate that this is a soft interrupt to the extent possible */ if (unlikely (int80_is_external ()))
@@ -210,11 +209,9 @@ DEFINE_FREDENTRY_RAW(int80_emulation) {int nr; -enter_from_user_mode (regs); +enter_from_user_mode_randomize_stack (regs);instrumentation_begin (); -add_random_kstack_offset (); -/* * FRED pushed 0 into regs::orig_ax and regs::ax contains the * syscall number.
@@ -252,10 +249,10 @@ DEFINE_FREDENTRY_RAW(int80_emulation)* orig_ax, the int return value truncates it. This matches * the semantics of syscall_get_nr(). */ - nr =syscall_enter_from_user_mode (regs, nr); + nr =syscall_enter_from_user_mode_randomize_stack (regs, nr); +instrumentation_begin (); -add_random_kstack_offset ();do_syscall_32_irqs_on (regs, nr);instrumentation_end ();
@@ -268,15 +265,9 @@ static noinstr bool __do_fast_syscall_32int nr =syscall_32_enter (regs);int res; -/* -* This cannot use syscall_enter_from_user_mode() as it has to -* fetch EBP before invoking any of the syscall entry work -* functions. -*/ -enter_from_user_mode (regs); +enter_from_user_mode_randomize_stack (regs);instrumentation_begin (); -add_random_kstack_offset ();local_irq_enable ();/* Fetch EBP from where the vDSO stashed it. */ if (IS_ENABLED (CONFIG_X86_64 )) {
arch/x86/entry/syscall_64.c +1 -2
@@ -86,10 +86,9 @@ static __always_inline bool do_syscall_x/* Returns true to return using SYSRET, or false to use IRET */ __visible noinstr bool do_syscall_64(struct pt_regs *regs, int nr) { - nr =syscall_enter_from_user_mode (regs, nr); + nr =syscall_enter_from_user_mode_randomize_stack (regs, nr);instrumentation_begin (); -add_random_kstack_offset ();if (!do_syscall_x64 (regs, nr) && !do_syscall_x32 (regs, nr) && nr !=-1 ) {/* Invalid system call, but still a system call. */
arch/x86/include/asm/entry-common.h +0 -1
@@ -2,7 +2,6 @@#ifndef _ASM_X86_ENTRY_COMMON_H#define _ASM_X86_ENTRY_COMMON_H -#include <linux/randomize_kstack.h> #include <linux/user-return-notifier.h> #include <asm/nospec-branch.h>
Re: [patch 08/18] x86/syscall: Use [syscall_]enter_from_user_mode_randomize_stack()
Quoted 94 lines · Thomas Gleixner
These functions integrate the stack randomization.
syscall_enter_from_user_mode_randomize_stack()has the advantage that the randomization happens early right afterenter_from_user_mode().In both cases also the overhead of get/put_cpu_var() in
add_random_kstack_offset()is avoided.No functional change.
Signed-off-by Thomas Gleixner <[email protected]>---
arch/x86/entry/syscall_32.c | 19 +++++-------------- arch/x86/entry/syscall_64.c | 3 +--arch/x86/include/asm/entry-common.h| 1 -3 files changed, 6 insertions(+), 17 deletions(-)arch/x86/entry/syscall_32.c +1
-1@@ -142,10 +142,9 @@ static __always_inline bool int80_is_ext* int80_is_external() below which calls into the APIC driver. * Identical for soft and external interrupts. */ -enter_from_user_mode (regs); +enter_from_user_mode_randomize_stack (regs);
instrumentation_begin();arch/x86/entry/syscall_32.c +0
-1-add_random_kstack_offset ();
/* Validate that this is a soft interrupt to the extent possible */ if (unlikely(int80_is_external()))arch/x86/entry/syscall_32.c +0
-0@@ -210,11 +209,9 @@ DEFINE_FREDENTRY_RAW(int80_emulation) { int nr;arch/x86/entry/syscall_32.c +1
-1-enter_from_user_mode (regs); +enter_from_user_mode_randomize_stack (regs);
instrumentation_begin();arch/x86/entry/syscall_32.c +0
-2-add_random_kstack_offset (); -/*
* FRED pushed 0 intoregs::orig_axandregs::axcontains the
* syscall number.arch/x86/entry/syscall_32.c +2
-1@@ -252,10 +249,10 @@ DEFINE_FREDENTRY_RAW(int80_emulation)* orig_ax, the int return value truncates it. This matches * the semantics of syscall_get_nr(). */ - nr =syscall_enter_from_user_mode (regs, nr); + nr =syscall_enter_from_user_mode_randomize_stack (regs, nr); + instrumentation_begin();arch/x86/entry/syscall_32.c +0
-1-add_random_kstack_offset ();
do_syscall_32_irqs_on(regs, nr);
instrumentation_end();arch/x86/entry/syscall_32.c +0
-0@@ -268,15 +265,9 @@ static noinstr bool __do_fast_syscall_32 int nr = syscall_32_enter(regs); int res;arch/x86/entry/syscall_32.c +1
-6-/* -* This cannot use syscall_enter_from_user_mode() as it has to -* fetch EBP before invoking any of the syscall entry work -* functions. -*/ -enter_from_user_mode (regs); +enter_from_user_mode_randomize_stack (regs);
instrumentation_begin();arch/x86/entry/syscall_32.c +0
-1-add_random_kstack_offset ();
local_irq_enable();
/* Fetch EBP from where the vDSO stashed it. */ if (IS_ENABLED(CONFIG_X86_64)) {arch/x86/entry/syscall_64.c +1
-1@@ -86,10 +86,9 @@ static __always_inline bool do_syscall_x /* Returns true to return using SYSRET, or false to use IRET */ __visible noinstr bool do_syscall_64(struct pt_regs *regs, int nr) { - nr =syscall_enter_from_user_mode (regs, nr); + nr =syscall_enter_from_user_mode_randomize_stack (regs, nr);
instrumentation_begin();arch/x86/entry/syscall_64.c +0
-1-add_random_kstack_offset ();
if (!do_syscall_x64(regs, nr) && !do_syscall_x32(regs, nr) && nr != -1) { /* Invalid system call, but still a system call. */arch/x86/include/asm/entry-common.h +0
-0@@ -2,7 +2,6 @@ #ifndef _ASM_X86_ENTRY_COMMON_H #define _ASM_X86_ENTRY_COMMON_H
Quoted 5 lines
-#include <linux/randomize_kstack.h>
#include <linux/user-return-notifier.h>
#include <asm/nospec-branch.h>
Re: [patch 08/18] x86/syscall: Use [syscall_]enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 10 lines · Thomas Gleixner
These functions integrate the stack randomization.
syscall_enter_from_user_mode_randomize_stack()has the advantage that the randomization happens early right afterenter_from_user_mode().In both cases also the overhead of get/put_cpu_var() in
add_random_kstack_offset()is avoided.No functional change.
Quoted 7 lines
Signed-off-by Thomas Gleixner <[email protected]>--- arch/x86/entry/syscall_32.c | 19 +++++-------------- arch/x86/entry/syscall_64.c | 3 +-- arch/x86/include/asm/entry-common.h | 1 - 3 files changed, 6 insertions(+), 17 deletions(-)
Quoted 83 lines
arch/x86/entry/syscall_32.c +5
-14@@ -142,10 +142,9 @@ static __always_inline bool int80_is_ext* int80_is_external() below which calls into the APIC driver. * Identical for soft and external interrupts. */ -enter_from_user_mode (regs); +enter_from_user_mode_randomize_stack (regs);instrumentation_begin (); -add_random_kstack_offset ();/* Validate that this is a soft interrupt to the extent possible */ if (unlikely (int80_is_external ()))@@ -210,11 +209,9 @@ DEFINE_FREDENTRY_RAW(int80_emulation) {int nr; -enter_from_user_mode (regs); +enter_from_user_mode_randomize_stack (regs);instrumentation_begin (); -add_random_kstack_offset (); -/* * FRED pushed 0 into regs::orig_ax and regs::ax contains the * syscall number. @@ -252,10 +249,10 @@ DEFINE_FREDENTRY_RAW(int80_emulation)* orig_ax, the int return value truncates it. This matches * the semantics of syscall_get_nr(). */ - nr =syscall_enter_from_user_mode (regs, nr); + nr =syscall_enter_from_user_mode_randomize_stack (regs, nr); +instrumentation_begin (); -add_random_kstack_offset ();do_syscall_32_irqs_on (regs, nr);instrumentation_end ();@@ -268,15 +265,9 @@ static noinstr bool __do_fast_syscall_32int nr =syscall_32_enter (regs);int res; -/* -* This cannot use syscall_enter_from_user_mode() as it has to -* fetch EBP before invoking any of the syscall entry work -* functions. -*/ -enter_from_user_mode (regs); +enter_from_user_mode_randomize_stack (regs);instrumentation_begin (); -add_random_kstack_offset ();local_irq_enable ();/* Fetch EBP from where the vDSO stashed it. */ if (IS_ENABLED (CONFIG_X86_64 )) {arch/x86/entry/syscall_64.c +1
-2@@ -86,10 +86,9 @@ static __always_inline bool do_syscall_x/* Returns true to return using SYSRET, or false to use IRET */ __visible noinstr bool do_syscall_64(struct pt_regs *regs, int nr) { - nr =syscall_enter_from_user_mode (regs, nr); + nr =syscall_enter_from_user_mode_randomize_stack (regs, nr);instrumentation_begin (); -add_random_kstack_offset ();if (!do_syscall_x64 (regs, nr) && !do_syscall_x32 (regs, nr) && nr !=-1 ) {/* Invalid system call, but still a system call. */ arch/x86/include/asm/entry-common.h +0
-1@@ -2,7 +2,6 @@#ifndef _ASM_X86_ENTRY_COMMON_H#define _ASM_X86_ENTRY_COMMON_H -#include <linux/randomize_kstack.h> #include <linux/user-return-notifier.h> #include <asm/nospec-branch.h>
Re: [patch 08/18] x86/syscall: Use [syscall_]enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 10 lines · Thomas Gleixner
These functions integrate the stack randomization.
syscall_enter_from_user_mode_randomize_stack()has the advantage that the randomization happens early right afterenter_from_user_mode().In both cases also the overhead of get/put_cpu_var() in
add_random_kstack_offset()is avoided.No functional change.
Quoted 7 lines
Signed-off-by Thomas Gleixner <[email protected]>--- arch/x86/entry/syscall_32.c | 19 +++++-------------- arch/x86/entry/syscall_64.c | 3 +-- arch/x86/include/asm/entry-common.h | 1 - 3 files changed, 6 insertions(+), 17 deletions(-)
Re: [patch 08/18] x86/syscall: Use [syscall_]enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerQuoted 93 lines · Thomas Gleixner
These functions integrate the stack randomization.
syscall_enter_from_user_mode_randomize_stack()has the advantage that the randomization happens early right afterenter_from_user_mode().In both cases also the overhead of get/put_cpu_var() in
add_random_kstack_offset()is avoided.No functional change.
Signed-off-by Thomas Gleixner <[email protected]>--- arch/x86/entry/syscall_32.c | 19 +++++-------------- arch/x86/entry/syscall_64.c | 3 +-- arch/x86/include/asm/entry-common.h | 1 - 3 files changed, 6 insertions(+), 17 deletions(-)arch/x86/entry/syscall_32.c +5
-14@@ -142,10 +142,9 @@ static __always_inline bool int80_is_ext* int80_is_external() below which calls into the APIC driver. * Identical for soft and external interrupts. */ -enter_from_user_mode (regs); +enter_from_user_mode_randomize_stack (regs);instrumentation_begin (); -add_random_kstack_offset ();/* Validate that this is a soft interrupt to the extent possible */ if (unlikely (int80_is_external ()))@@ -210,11 +209,9 @@ DEFINE_FREDENTRY_RAW(int80_emulation) {int nr; -enter_from_user_mode (regs); +enter_from_user_mode_randomize_stack (regs);instrumentation_begin (); -add_random_kstack_offset (); -/* * FRED pushed 0 into regs::orig_ax and regs::ax contains the * syscall number. @@ -252,10 +249,10 @@ DEFINE_FREDENTRY_RAW(int80_emulation)* orig_ax, the int return value truncates it. This matches * the semantics of syscall_get_nr(). */ - nr =syscall_enter_from_user_mode (regs, nr); + nr =syscall_enter_from_user_mode_randomize_stack (regs, nr); +instrumentation_begin (); -add_random_kstack_offset ();do_syscall_32_irqs_on (regs, nr);instrumentation_end ();@@ -268,15 +265,9 @@ static noinstr bool __do_fast_syscall_32int nr =syscall_32_enter (regs);int res; -/* -* This cannot use syscall_enter_from_user_mode() as it has to -* fetch EBP before invoking any of the syscall entry work -* functions. -*/ -enter_from_user_mode (regs); +enter_from_user_mode_randomize_stack (regs);instrumentation_begin (); -add_random_kstack_offset ();local_irq_enable ();/* Fetch EBP from where the vDSO stashed it. */ if (IS_ENABLED (CONFIG_X86_64 )) {arch/x86/entry/syscall_64.c +1
-2@@ -86,10 +86,9 @@ static __always_inline bool do_syscall_x/* Returns true to return using SYSRET, or false to use IRET */ __visible noinstr bool do_syscall_64(struct pt_regs *regs, int nr) { - nr =syscall_enter_from_user_mode (regs, nr); + nr =syscall_enter_from_user_mode_randomize_stack (regs, nr);instrumentation_begin (); -add_random_kstack_offset ();if (!do_syscall_x64 (regs, nr) && !do_syscall_x32 (regs, nr) && nr !=-1 ) {/* Invalid system call, but still a system call. */
arch/x86/include/asm/entry-common.h line 7
Quoted 7 lines
arch/x86/include/asm/entry-common.h +0
-1@@ -2,7 +2,6 @@#ifndef _ASM_X86_ENTRY_COMMON_H#define _ASM_X86_ENTRY_COMMON_H -#include <linux/randomize_kstack.h> #include <linux/user-return-notifier.h> #include <asm/nospec-branch.h>
[tip: core/entry] x86/syscall: Use [syscall_]enter_from_user_mode_randomize_stack()
In reply to Thomas GleixnerThe following commit has been merged into the core/entry branch of tip:
The following commit has been merged into the core/entry branch of tip:
Commit-ID: 9d311796e2ce75b3aaded2719a01d7e248c3a24f Gitweb: https://git.kernel.org/tip/9d311796e2ce75b3aaded2719a01d7e248c3a24f Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 07 Jul 2026 21:06:27 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Sun, 12 Jul 2026 12:38:01 +02:00
x86/syscall: Use [syscall_]enter_from_user_mode_randomize_stack()
These functions integrate the stack randomization.
syscall_enter_from_user_mode_randomize_stack() has the advantage that the randomization happens early right after enter_from_user_mode().
In both cases also the overhead of get/put_cpu_var() in add_random_kstack_offset() is avoided.
No functional change.
--- arch/x86/entry/syscall_32.c | 19 +++++-------------- arch/x86/entry/syscall_64.c | 3 +-- arch/x86/include/asm/entry-common.h | 1 - 3 files changed, 6 insertions(+), 17 deletions(-)
arch/x86/entry/syscall_32.c +5 -14
@@ -142,10 +142,9 @@ __visible noinstr void do_int80_emulation(struct pt_regs *regs)* int80_is_external() below which calls into the APIC driver. * Identical for soft and external interrupts. */ -enter_from_user_mode (regs); +enter_from_user_mode_randomize_stack (regs);instrumentation_begin (); -add_random_kstack_offset ();/* Validate that this is a soft interrupt to the extent possible */ if (unlikely (int80_is_external ()))
@@ -210,11 +209,9 @@ DEFINE_FREDENTRY_RAW(int80_emulation) {int nr; -enter_from_user_mode (regs); +enter_from_user_mode_randomize_stack (regs);instrumentation_begin (); -add_random_kstack_offset (); -/* * FRED pushed 0 into regs::orig_ax and regs::ax contains the * syscall number.
@@ -252,10 +249,10 @@ __visible noinstr void do_int80_syscall_32(struct pt_regs *regs)* orig_ax, the int return value truncates it. This matches * the semantics of syscall_get_nr(). */ - nr =syscall_enter_from_user_mode (regs, nr); + nr =syscall_enter_from_user_mode_randomize_stack (regs, nr); +instrumentation_begin (); -add_random_kstack_offset ();do_syscall_32_irqs_on (regs, nr);instrumentation_end ();
@@ -268,15 +265,9 @@ static noinstr bool __do_fast_syscall_32(struct pt_regs *regs)int nr =syscall_32_enter (regs);int res; -/* -* This cannot use syscall_enter_from_user_mode() as it has to -* fetch EBP before invoking any of the syscall entry work -* functions. -*/ -enter_from_user_mode (regs); +enter_from_user_mode_randomize_stack (regs);instrumentation_begin (); -add_random_kstack_offset ();local_irq_enable ();/* Fetch EBP from where the vDSO stashed it. */ if (IS_ENABLED (CONFIG_X86_64 )) {
arch/x86/entry/syscall_64.c +1 -2
@@ -86,10 +86,9 @@ static __always_inline bool do_syscall_x32(struct pt_regs *regs, int nr)/* Returns true to return using SYSRET, or false to use IRET */ __visible noinstr bool do_syscall_64(struct pt_regs *regs, int nr) { - nr =syscall_enter_from_user_mode (regs, nr); + nr =syscall_enter_from_user_mode_randomize_stack (regs, nr);instrumentation_begin (); -add_random_kstack_offset ();if (!do_syscall_x64 (regs, nr) && !do_syscall_x32 (regs, nr) && nr !=-1 ) {/* Invalid system call, but still a system call. */
arch/x86/include/asm/entry-common.h +0 -1
@@ -2,7 +2,6 @@#ifndef _ASM_X86_ENTRY_COMMON_H#define _ASM_X86_ENTRY_COMMON_H -#include <linux/randomize_kstack.h> #include <linux/user-return-notifier.h> #include <asm/nospec-branch.h>
Thomas Gleixner
maintainerPATCH 9/18 entry: Remove syscall_enter_from_user_mode()
In reply to Thomas GleixnerAll architecture use either:
nr = enter_from_user_mode_randomize_stack(regs, nr);
or
enter_from_user_mode_randomize_stack(regs);
nr = syscall_enter_from_user_mode_work(regs, nr);Remove the now unused function.
--- Documentation/core-api/entry.rst | 17 +++++++++------- include/linux/entry-common.h | 40 +++------------------------------------ include/linux/irq-entry-common.h | 6 ++--- 3 files changed, 17 insertions(+), 46 deletions(-)
Documentation/core-api/entry.rst +10 -7
@@ -68,7 +68,7 @@ low-level C code must not be instrumente noinstr void syscall(struct pt_regs *regs, int nr) { arch_syscall_enter(regs); - nr = syscall_enter_from_user_mode(regs, nr); + nr = syscall_enter_from_user_mode_randomize_stack(regs, nr); instrumentation_begin(); if (!invoke_syscall(regs, nr) && nr != -1)
@@ -78,12 +78,14 @@ low-level C code must not be instrumente syscall_exit_to_user_mode(regs); } -syscall_enter_from_user_mode() first invokes enter_from_user_mode() which -establishes state in the following order: +syscall_enter_from_user_mode_randomize_stack() first invokes +enter_from_user_mode_randomize_stack() which establishes state in the +following order: * Lockdep * RCU / Context tracking * Tracing + * Apply stack randomization and then invokes the various entry work functions like ptrace, seccomp, audit, syscall tracing, etc. After all that is done, the instrumentable invoke_syscall
@@ -99,10 +101,11 @@ that it invokes exit_to_user_mode() whic * RCU / Context tracking * Lockdep -syscall_enter_from_user_mode() and syscall_exit_to_user_mode() are also -available as fine grained subfunctions in cases where the architecture code -has to do extra work between the various steps. In such cases it has to -ensure that enter_from_user_mode() is called first on entry and +syscall_enter_from_user_mode_randomize_stack() and +syscall_exit_to_user_mode() are also available as fine grained subfunctions +in cases where the architecture code has to do extra work between the +various steps. In such cases it has to ensure that +enter_from_user_mode_randomize_stack() is called first on entry and exit_to_user_mode() is called last on exit. Do not nest syscalls. Nested syscalls will cause RCU and/or context tracking
include/linux/entry-common.h +4 -36
@@ -19,7 +19,7 @@#endif /* -* SYSCALL_WORK flags handled in syscall_enter_from_user_mode() +* SYSCALL_WORK flags handled in syscall_enter_from_user_mode_work() */ #define SYSCALL_WORK_ENTER (SYSCALL_WORK_SECCOMP | \ SYSCALL_WORK_SYSCALL_TRACEPOINT | \
@@ -205,42 +205,10 @@ do { \ _ret; \ }) -/** -* syscall_enter_from_user_mode - Establish state and check and handle work -* before invoking a syscall -* @regs: Pointer to currents pt_regs -* @syscall: The syscall number -* -* Invoked from architecture specific syscall entry code with interrupts -* disabled. The calling code has to be non-instrumentable. When the -* function returns all state is correct, interrupts are enabled and the -* subsequent functions can be instrumented. -* -* This is the combination of enter_from_user_mode() and -* syscall_enter_from_user_mode_work() to be used when there is no -* architecture specific work to be done between the two. -* -* Returns: The original or a modified syscall number. See -* syscall_enter_from_user_mode_work() for further explanation. -*/ -static __always_inline long syscall_enter_from_user_mode (struct pt_regs *regs,long syscall) -{ -long ret; - -enter_from_user_mode (regs); - -instrumentation_begin (); -local_irq_enable (); - ret =syscall_enter_from_user_mode_work (regs, syscall); -instrumentation_end (); - -return ret; -} -/* -* If SYSCALL_EMU is set, then the only reason to report is when -* SINGLESTEP is set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall -* instruction has been already reported in syscall_enter_from_user_mode(). +* If SYSCALL_EMU is set, then the only reason to report is when SINGLESTEP is +* set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall instruction has been +* already reported in syscall_enter_from_user_mode_work(). */ static __always_inline bool report_single_step(unsigned long work) {
include/linux/irq-entry-common.h +3 -3
@@ -49,9 +49,9 @@* Defaults to an empty implementation. Can be replaced by architecture * specific code. * -* Invoked from syscall_enter_from_user_mode() in the non-instrumentable -* section. Use __always_inline so the compiler cannot push it out of line -* and make it instrumentable. +* Invoked from enter_from_user_mode_syscall_and_randomize_stack() in the +* non-instrumentable section. Use __always_inline so the compiler cannot push +* it out of line and make it instrumentable. */ static __always_inline void arch_enter_from_user_mode(struct pt_regs *regs);
Re: [patch 09/18] entry: Remove syscall_enter_from_user_mode()
Quoted 3 lines · Thomas Gleixner
All architecture use either:
nr =
enter_from_user_mode_randomize_stack(regs, nr);
You probably mean syscall_enter_from_user_mode_randomize_stack.
Quoted 119 lines
or
enter_from_user_mode_randomize_stack(regs); nr =syscall_enter_from_user_mode_work(regs, nr);Remove the now unused function.
Signed-off-by Thomas Gleixner <[email protected]>---
Documentation/core-api/entry.rst | 17 +++++++++------- include/linux/entry-common.h | 40 +++------------------------------------include/linux/irq-entry-common.h| 6 ++---3 files changed, 17 insertions(+), 46 deletions(-)Documentation/core-api/entry.rst +1
-1@@ -68,7 +68,7 @@ low-level C code must not be instrumente noinstr void syscall(struct pt_regs *regs, int nr) { arch_syscall_enter(regs); - nr = syscall_enter_from_user_mode(regs, nr); + nr = syscall_enter_from_user_mode_randomize_stack(regs, nr);
instrumentation_begin();
if (!invoke_syscall(regs, nr) && nr != -1)Documentation/core-api/entry.rst +0
-0@@ -78,12 +78,14 @@ low-level C code must not be instrumente syscall_exit_to_user_mode(regs); }Documentation/core-api/entry.rst +3
-2-syscall_enter_from_user_mode() first invokes enter_from_user_mode() which -establishes state in the following order: +syscall_enter_from_user_mode_randomize_stack() first invokes +enter_from_user_mode_randomize_stack() which establishes state in the +following order:
* Lockdep
* RCU / Context tracking
* Tracing
+ * Apply stack randomization
and then invokes the various entry work functions like ptrace, seccomp, audit, syscall tracing, etc. After all that is done, the instrumentableinvoke_syscallDocumentation/core-api/entry.rst +0
-0@@ -99,10 +101,11 @@ that it invokes exit_to_user_mode() whic * RCU / Context tracking * LockdepDocumentation/core-api/entry.rst +5
-4-syscall_enter_from_user_mode() and syscall_exit_to_user_mode() are also -available as fine grained subfunctions in cases where the architecture code -has to do extra work between the various steps. In such cases it has to -ensure that enter_from_user_mode() is called first on entry and +syscall_enter_from_user_mode_randomize_stack() and +syscall_exit_to_user_mode() are also available as fine grained subfunctions +in cases where the architecture code has to do extra work between the +various steps. In such cases it has to ensure that +enter_from_user_mode_randomize_stack() is called first on entry andexit_to_user_mode() is called last on exit.
Do not nest syscalls. Nested syscalls will cause RCU and/or context trackinginclude/linux/entry-common.h +0
-0@@ -19,7 +19,7 @@ #endif
/*
- *SYSCALL_WORKflags handled insyscall_enter_from_user_mode()
+ *SYSCALL_WORKflags handled insyscall_enter_from_user_mode_work()*/
#defineSYSCALL_WORK_ENTER(SYSCALL_WORK_SECCOMP| \
SYSCALL_WORK_SYSCALL_TRACEPOINT| \include/linux/entry-common.h +0
-0@@ -205,42 +205,10 @@ do { \ _ret; \ })include/linux/entry-common.h +0
-32-/** -* syscall_enter_from_user_mode - Establish state and check and handle work -* before invoking a syscall -* @regs: Pointer to currents pt_regs -* @syscall: The syscall number -* -* Invoked from architecture specific syscall entry code with interrupts -* disabled. The calling code has to be non-instrumentable. When the -* function returns all state is correct, interrupts are enabled and the -* subsequent functions can be instrumented. -* -* This is the combination of enter_from_user_mode() and -* syscall_enter_from_user_mode_work() to be used when there is no -* architecture specific work to be done between the two. -* -* Returns: The original or a modified syscall number. See -* syscall_enter_from_user_mode_work() for further explanation. -*/ -static __always_inline long syscall_enter_from_user_mode (struct pt_regs *regs,long syscall) -{ -long ret; - -enter_from_user_mode (regs); - -instrumentation_begin (); -local_irq_enable (); - ret =syscall_enter_from_user_mode_work (regs, syscall); -instrumentation_end (); - -return ret; -} -/*
- * IfSYSCALL_EMUis set, then the only reason to report is when
- * SINGLESTEP is set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall
- * instruction has been already reported insyscall_enter_from_user_mode().
+ * IfSYSCALL_EMUis set, then the only reason to report is when SINGLESTEP is
+ * set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall instruction has been
+ * already reported insyscall_enter_from_user_mode_work().
*/
static__always_inlineboolreport_single_step(unsigned long work){
include/linux/irq-entry-common.h line 52
Quoted 7 lines
include/linux/irq-entry-common.h +1
-3@@ -49,9 +49,9 @@ * Defaults to an empty implementation. Can be replaced by architecture * specific code. * - * Invoked from syscall_enter_from_user_mode() in the non-instrumentable - * section. Use __always_inline so the compiler cannot push it out of line - * and make it instrumentable. + * Invoked from enter_from_user_mode_syscall_and_randomize_stack() in the
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Probably syscall_enter_from_user_mode_randomize_stack()? But the reality is it's only ever invoked from enter_from_user_mode(), which is below in the same file (include/linux/irq-entry-common.h).
Granted, that's an always inline function, and it's used by both macros you added (since the second one uses the first one).
Quoted 5 lines
include/linux/irq-entry-common.h +2
-0+* non-instrumentable section. Use __always_inline so the compiler cannot push +* it out of line and make it instrumentable. */ static __always_inline void arch_enter_from_user_mode(struct pt_regs *regs);
Thomas Gleixner
maintainerRe: [patch 09/18] entry: Remove syscall_enter_from_user_mode()
Quoted 6 lines · Radu Rendec
Quoted 3 lines · Thomas Gleixner
All architecture use either:
nr =
enter_from_user_mode_randomize_stack(regs, nr);You probably mean
syscall_enter_from_user_mode_randomize_stack.
Duh. I obviously got that wrong in a hurry. Thanks for pointing it out!
Quoted 14 lines
include/linux/irq-entry-common.h line 52
Quoted 12 lines
static
__always_inlineboolreport_single_step(unsigned long work){include/linux/irq-entry-common.h +1
-3@@ -49,9 +49,9 @@ * Defaults to an empty implementation. Can be replaced by architecture * specific code. * - * Invoked from syscall_enter_from_user_mode() in the non-instrumentable - * section. Use __always_inline so the compiler cannot push it out of line - * and make it instrumentable. + * Invoked from enter_from_user_mode_syscall_and_randomize_stack() in the^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Quoted 3 lines
Probably
syscall_enter_from_user_mode_randomize_stack()? But the reality is it's only ever invoked fromenter_from_user_mode(), which is below in the same file (include/linux/irq-entry-common.h).
Yes. Indeed.
Re: [patch 09/18] entry: Remove syscall_enter_from_user_mode()
In reply to Thomas GleixnerQuoted 122 lines · Thomas Gleixner
All architecture use either:
nr = enter_from_user_mode_randomize_stack(regs, nr);or
enter_from_user_mode_randomize_stack(regs); nr = syscall_enter_from_user_mode_work(regs, nr);Remove the now unused function.
Signed-off-by Thomas Gleixner <[email protected]>--- Documentation/core-api/entry.rst | 17 +++++++++------- include/linux/entry-common.h | 40 +++------------------------------------ include/linux/irq-entry-common.h | 6 ++--- 3 files changed, 17 insertions(+), 46 deletions(-)Documentation/core-api/entry.rst +10
-7@@ -68,7 +68,7 @@ low-level C code must not be instrumente noinstr void syscall(struct pt_regs *regs, int nr) { arch_syscall_enter(regs); - nr = syscall_enter_from_user_mode(regs, nr); + nr = syscall_enter_from_user_mode_randomize_stack(regs, nr); instrumentation_begin(); if (!invoke_syscall(regs, nr) && nr != -1)@@ -78,12 +78,14 @@ low-level C code must not be instrumente syscall_exit_to_user_mode(regs); } -syscall_enter_from_user_mode() first invokes enter_from_user_mode() which -establishes state in the following order: +syscall_enter_from_user_mode_randomize_stack() first invokes +enter_from_user_mode_randomize_stack() which establishes state in the +following order: * Lockdep * RCU / Context tracking * Tracing + * Apply stack randomization and then invokes the various entry work functions like ptrace, seccomp, audit, syscall tracing, etc. After all that is done, the instrumentable invoke_syscall@@ -99,10 +101,11 @@ that it invokes exit_to_user_mode() whic * RCU / Context tracking * Lockdep -syscall_enter_from_user_mode() and syscall_exit_to_user_mode() are also -available as fine grained subfunctions in cases where the architecture code -has to do extra work between the various steps. In such cases it has to -ensure that enter_from_user_mode() is called first on entry and +syscall_enter_from_user_mode_randomize_stack() and +syscall_exit_to_user_mode() are also available as fine grained subfunctions +in cases where the architecture code has to do extra work between the +various steps. In such cases it has to ensure that +enter_from_user_mode_randomize_stack() is called first on entry and exit_to_user_mode() is called last on exit. Do not nest syscalls. Nested syscalls will cause RCU and/or context trackinginclude/linux/entry-common.h +4
-36@@ -19,7 +19,7 @@#endif /* -* SYSCALL_WORK flags handled in syscall_enter_from_user_mode() +* SYSCALL_WORK flags handled in syscall_enter_from_user_mode_work() */ #define SYSCALL_WORK_ENTER (SYSCALL_WORK_SECCOMP | \ SYSCALL_WORK_SYSCALL_TRACEPOINT | \@@ -205,42 +205,10 @@ do { \ _ret; \ }) -/** -* syscall_enter_from_user_mode - Establish state and check and handle work -* before invoking a syscall -* @regs: Pointer to currents pt_regs -* @syscall: The syscall number -* -* Invoked from architecture specific syscall entry code with interrupts -* disabled. The calling code has to be non-instrumentable. When the -* function returns all state is correct, interrupts are enabled and the -* subsequent functions can be instrumented. -* -* This is the combination of enter_from_user_mode() and -* syscall_enter_from_user_mode_work() to be used when there is no -* architecture specific work to be done between the two. -* -* Returns: The original or a modified syscall number. See -* syscall_enter_from_user_mode_work() for further explanation. -*/ -static __always_inline long syscall_enter_from_user_mode (struct pt_regs *regs,long syscall) -{ -long ret; - -enter_from_user_mode (regs); - -instrumentation_begin (); -local_irq_enable (); - ret =syscall_enter_from_user_mode_work (regs, syscall); -instrumentation_end (); - -return ret; -} -/* -* If SYSCALL_EMU is set, then the only reason to report is when -* SINGLESTEP is set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall -* instruction has been already reported in syscall_enter_from_user_mode(). +* If SYSCALL_EMU is set, then the only reason to report is when SINGLESTEP is +* set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall instruction has been +* already reported in syscall_enter_from_user_mode_work(). */ static __always_inline bool report_single_step(unsigned long work) {
include/linux/irq-entry-common.h line 54
Quoted 9 lines
include/linux/irq-entry-common.h +3
-3@@ -49,9 +49,9 @@* Defaults to an empty implementation. Can be replaced by architecture * specific code. * -* Invoked from syscall_enter_from_user_mode() in the non-instrumentable -* section. Use __always_inline so the compiler cannot push it out of line -* and make it instrumentable. +* Invoked from enter_from_user_mode_syscall_and_randomize_stack() in the +* non-instrumentable section. Use __always_inline so the compiler cannot push +* it out of line and make it instrumentable.
Quoted 4 lines
include/linux/irq-entry-common.h +0
-0*/ static __always_inline void arch_enter_from_user_mode(struct pt_regs *regs);
Re: [patch 09/18] entry: Remove syscall_enter_from_user_mode()
In reply to Thomas GleixnerQuoted 125 lines · Thomas Gleixner
All architecture use either:
nr = enter_from_user_mode_randomize_stack(regs, nr);or
enter_from_user_mode_randomize_stack(regs); nr = syscall_enter_from_user_mode_work(regs, nr);Remove the now unused function.
Signed-off-by Thomas Gleixner <[email protected]>--- Documentation/core-api/entry.rst | 17 +++++++++------- include/linux/entry-common.h | 40 +++------------------------------------ include/linux/irq-entry-common.h | 6 ++--- 3 files changed, 17 insertions(+), 46 deletions(-)Documentation/core-api/entry.rst +10
-7@@ -68,7 +68,7 @@ low-level C code must not be instrumente noinstr void syscall(struct pt_regs *regs, int nr) { arch_syscall_enter(regs); - nr = syscall_enter_from_user_mode(regs, nr); + nr = syscall_enter_from_user_mode_randomize_stack(regs, nr); instrumentation_begin(); if (!invoke_syscall(regs, nr) && nr != -1)@@ -78,12 +78,14 @@ low-level C code must not be instrumente syscall_exit_to_user_mode(regs); } -syscall_enter_from_user_mode() first invokes enter_from_user_mode() which -establishes state in the following order: +syscall_enter_from_user_mode_randomize_stack() first invokes +enter_from_user_mode_randomize_stack() which establishes state in the +following order: * Lockdep * RCU / Context tracking * Tracing + * Apply stack randomization and then invokes the various entry work functions like ptrace, seccomp, audit, syscall tracing, etc. After all that is done, the instrumentable invoke_syscall@@ -99,10 +101,11 @@ that it invokes exit_to_user_mode() whic * RCU / Context tracking * Lockdep -syscall_enter_from_user_mode() and syscall_exit_to_user_mode() are also -available as fine grained subfunctions in cases where the architecture code -has to do extra work between the various steps. In such cases it has to -ensure that enter_from_user_mode() is called first on entry and +syscall_enter_from_user_mode_randomize_stack() and +syscall_exit_to_user_mode() are also available as fine grained subfunctions +in cases where the architecture code has to do extra work between the +various steps. In such cases it has to ensure that +enter_from_user_mode_randomize_stack() is called first on entry and exit_to_user_mode() is called last on exit. Do not nest syscalls. Nested syscalls will cause RCU and/or context trackinginclude/linux/entry-common.h +4
-36@@ -19,7 +19,7 @@#endif /* -* SYSCALL_WORK flags handled in syscall_enter_from_user_mode() +* SYSCALL_WORK flags handled in syscall_enter_from_user_mode_work() */ #define SYSCALL_WORK_ENTER (SYSCALL_WORK_SECCOMP | \ SYSCALL_WORK_SYSCALL_TRACEPOINT | \@@ -205,42 +205,10 @@ do { \ _ret; \ }) -/** -* syscall_enter_from_user_mode - Establish state and check and handle work -* before invoking a syscall -* @regs: Pointer to currents pt_regs -* @syscall: The syscall number -* -* Invoked from architecture specific syscall entry code with interrupts -* disabled. The calling code has to be non-instrumentable. When the -* function returns all state is correct, interrupts are enabled and the -* subsequent functions can be instrumented. -* -* This is the combination of enter_from_user_mode() and -* syscall_enter_from_user_mode_work() to be used when there is no -* architecture specific work to be done between the two. -* -* Returns: The original or a modified syscall number. See -* syscall_enter_from_user_mode_work() for further explanation. -*/ -static __always_inline long syscall_enter_from_user_mode (struct pt_regs *regs,long syscall) -{ -long ret; - -enter_from_user_mode (regs); - -instrumentation_begin (); -local_irq_enable (); - ret =syscall_enter_from_user_mode_work (regs, syscall); -instrumentation_end (); - -return ret; -} -/* -* If SYSCALL_EMU is set, then the only reason to report is when -* SINGLESTEP is set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall -* instruction has been already reported in syscall_enter_from_user_mode(). +* If SYSCALL_EMU is set, then the only reason to report is when SINGLESTEP is +* set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall instruction has been +* already reported in syscall_enter_from_user_mode_work(). */ static __always_inline bool report_single_step(unsigned long work) {include/linux/irq-entry-common.h +0
-0@@ -49,9 +49,9 @@* Defaults to an empty implementation. Can be replaced by architecture * specific code.
include/linux/irq-entry-common.h line 57
Quoted 10 lines
include/linux/irq-entry-common.h +3
-3* -* Invoked from syscall_enter_from_user_mode() in the non-instrumentable -* section. Use __always_inline so the compiler cannot push it out of line -* and make it instrumentable. +* Invoked from enter_from_user_mode_syscall_and_randomize_stack() in the +* non-instrumentable section. Use __always_inline so the compiler cannot push +* it out of line and make it instrumentable. */ static __always_inline void arch_enter_from_user_mode(struct pt_regs *regs);
[tip: core/entry] entry: Remove syscall_enter_from_user_mode()
In reply to Thomas GleixnerThe following commit has been merged into the core/entry branch of tip:
The following commit has been merged into the core/entry branch of tip:
Commit-ID: bad2a27ba8c4a6bd2c47e598898d9dbd0f98511f Gitweb: https://git.kernel.org/tip/bad2a27ba8c4a6bd2c47e598898d9dbd0f98511f Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 07 Jul 2026 21:06:32 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Sun, 12 Jul 2026 12:38:01 +02:00
entry: Remove syscall_enter_from_user_mode()
All architecture use either:
nr = syscall_enter_from_user_mode_randomize_stack(regs, nr);
or
enter_from_user_mode_randomize_stack(regs);
nr = syscall_enter_from_user_mode_work(regs, nr);Remove the now unused function.
--- Documentation/core-api/entry.rst | 17 +++++++------ include/linux/entry-common.h | 40 +++---------------------------- include/linux/irq-entry-common.h | 6 ++--- 3 files changed, 17 insertions(+), 46 deletions(-)
Documentation/core-api/entry.rst +10 -7
@@ -68,7 +68,7 @@ invoked from low-level assembly code looks like this: noinstr void syscall(struct pt_regs *regs, int nr) { arch_syscall_enter(regs); - nr = syscall_enter_from_user_mode(regs, nr); + nr = syscall_enter_from_user_mode_randomize_stack(regs, nr); instrumentation_begin(); if (!invoke_syscall(regs, nr) && nr != -1)
@@ -78,12 +78,14 @@ invoked from low-level assembly code looks like this: syscall_exit_to_user_mode(regs); } -syscall_enter_from_user_mode() first invokes enter_from_user_mode() which -establishes state in the following order: +syscall_enter_from_user_mode_randomize_stack() first invokes +enter_from_user_mode_randomize_stack() which establishes state in the +following order: * Lockdep * RCU / Context tracking * Tracing + * Apply stack randomization and then invokes the various entry work functions like ptrace, seccomp, audit, syscall tracing, etc. After all that is done, the instrumentable invoke_syscall
@@ -99,10 +101,11 @@ transition in the reverse order: * RCU / Context tracking * Lockdep -syscall_enter_from_user_mode() and syscall_exit_to_user_mode() are also -available as fine grained subfunctions in cases where the architecture code -has to do extra work between the various steps. In such cases it has to -ensure that enter_from_user_mode() is called first on entry and +syscall_enter_from_user_mode_randomize_stack() and +syscall_exit_to_user_mode() are also available as fine grained subfunctions +in cases where the architecture code has to do extra work between the +various steps. In such cases it has to ensure that +enter_from_user_mode_randomize_stack() is called first on entry and exit_to_user_mode() is called last on exit. Do not nest syscalls. Nested syscalls will cause RCU and/or context tracking
include/linux/entry-common.h +4 -36
@@ -20,7 +20,7 @@#endif /* -* SYSCALL_WORK flags handled in syscall_enter_from_user_mode() +* SYSCALL_WORK flags handled in syscall_enter_from_user_mode_work() */ #define SYSCALL_WORK_ENTER (SYSCALL_WORK_SECCOMP | \ SYSCALL_WORK_SYSCALL_TRACEPOINT | \
@@ -205,42 +205,10 @@ do { \ _ret; \ }) -/** -* syscall_enter_from_user_mode - Establish state and check and handle work -* before invoking a syscall -* @regs: Pointer to currents pt_regs -* @syscall: The syscall number -* -* Invoked from architecture specific syscall entry code with interrupts -* disabled. The calling code has to be non-instrumentable. When the -* function returns all state is correct, interrupts are enabled and the -* subsequent functions can be instrumented. -* -* This is the combination of enter_from_user_mode() and -* syscall_enter_from_user_mode_work() to be used when there is no -* architecture specific work to be done between the two. -* -* Returns: The original or a modified syscall number. See -* syscall_enter_from_user_mode_work() for further explanation. -*/ -static __always_inline long syscall_enter_from_user_mode (struct pt_regs *regs,long syscall) -{ -long ret; - -enter_from_user_mode (regs); - -instrumentation_begin (); -local_irq_enable (); - ret =syscall_enter_from_user_mode_work (regs, syscall); -instrumentation_end (); - -return ret; -} -/* -* If SYSCALL_EMU is set, then the only reason to report is when -* SINGLESTEP is set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall -* instruction has been already reported in syscall_enter_from_user_mode(). +* If SYSCALL_EMU is set, then the only reason to report is when SINGLESTEP is +* set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall instruction has been +* already reported in syscall_enter_from_user_mode_work(). */ static __always_inline bool report_single_step(unsigned long work) {
include/linux/irq-entry-common.h +3 -3
@@ -49,9 +49,9 @@* Defaults to an empty implementation. Can be replaced by architecture * specific code. * -* Invoked from syscall_enter_from_user_mode() in the non-instrumentable -* section. Use __always_inline so the compiler cannot push it out of line -* and make it instrumentable. +* Invoked from enter_from_user_mode() in the non-instrumentable section. Use +* __always_inline so the compiler cannot push it out of line and make it +* instrumentable. */ static __always_inline void arch_enter_from_user_mode(struct pt_regs *regs);
Thomas Gleixner
maintainerPATCH 10/18 entry: Use syscall number instead of rereading it
In reply to Thomas Gleixnerrseq_syscall_enter_work() is invoked before the syscall number can be modified. So there is no point in rereading it from pt_regs.
--- include/linux/entry-common.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
include/linux/entry-common.h +5 -4
@@ -70,9 +70,10 @@ static inline void syscall_enter_audit(s } } -static __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work) +static __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work, +long syscall) { -long syscall, ret =0 ; +long ret =0 ;/* * Handle Syscall User Dispatch. This must comes first, since
@@ -90,7 +91,7 @@ static __always_inline long syscall_trac* through hrtimer_interrupt(). */ if (work &SYSCALL_WORK_SYSCALL_RSEQ_SLICE ) -rseq_syscall_enter_work (syscall_get_nr (current, regs)); +rseq_syscall_enter_work (syscall);/* Handle ptrace */ if (work & (SYSCALL_WORK_SYSCALL_TRACE |SYSCALL_WORK_SYSCALL_EMU )) {
@@ -145,7 +146,7 @@ static __always_inline long syscall_enteunsigned long work =READ_ONCE (current_thread_info ()->syscall_work);if (work &SYSCALL_WORK_ENTER ) - syscall =syscall_trace_enter (regs, work); + syscall =syscall_trace_enter (regs, work, syscall);return syscall; }
Re: [patch 10/18] entry: Use syscall number instead of rereading it
Quoted 38 lines · Thomas Gleixner
rseq_syscall_enter_work()is invoked before the syscall number can be modified. So there is no point in rereading it frompt_regs.Signed-off-by Thomas Gleixner <[email protected]>---
include/linux/entry-common.h | 9 +++++----1 file changed, 5 insertions(+), 4 deletions(-)include/linux/entry-common.h +0
-0@@ -70,9 +70,10 @@ static inline void syscall_enter_audit(s } }include/linux/entry-common.h +2
-1-static __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work) +static __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work, +long syscall){
include/linux/entry-common.h +1
-1-long syscall, ret =0 ; +long ret =0 ;
/*
* Handle Syscall User Dispatch. This must comes first, sinceinclude/linux/entry-common.h +1
-1@@ -90,7 +91,7 @@ static __always_inline long syscall_trac* through hrtimer_interrupt(). */ if (work & SYSCALL_WORK_SYSCALL_RSEQ_SLICE) -rseq_syscall_enter_work (syscall_get_nr (current, regs)); +rseq_syscall_enter_work (syscall);
/* Handle ptrace */
if (work & (SYSCALL_WORK_SYSCALL_TRACE|SYSCALL_WORK_SYSCALL_EMU)) {include/linux/entry-common.h +0
-0@@ -145,7 +146,7 @@ static __always_inline long syscall_ente unsigned long work = READ_ONCE(current_thread_info()->syscall_work);
if (work &SYSCALL_WORK_ENTER)include/linux/entry-common.h +1
-1- syscall =syscall_trace_enter (regs, work); + syscall =syscall_trace_enter (regs, work, syscall);
Quoted 3 lines
return syscall;
}
Re: [patch 10/18] entry: Use syscall number instead of rereading it
In reply to Thomas GleixnerQuoted 33 lines · Thomas Gleixner
rseq_syscall_enter_work()is invoked before the syscall number can be modified. So there is no point in rereading it frompt_regs.Signed-off-by Thomas Gleixner <[email protected]>--- include/linux/entry-common.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)include/linux/entry-common.h +4
-3@@ -70,9 +70,10 @@ static inline void syscall_enter_audit(s } } -static __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work) +static __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work, +long syscall) { -long syscall, ret =0 ; +long ret =0 ;/* * Handle Syscall User Dispatch. This must comes first, since @@ -90,7 +91,7 @@ static __always_inline long syscall_trac* through hrtimer_interrupt(). */ if (work &SYSCALL_WORK_SYSCALL_RSEQ_SLICE ) -rseq_syscall_enter_work (syscall_get_nr (current, regs)); +rseq_syscall_enter_work (syscall);/* Handle ptrace */ if (work & (SYSCALL_WORK_SYSCALL_TRACE |SYSCALL_WORK_SYSCALL_EMU )) {
include/linux/entry-common.h static __always_inline long syscall_ente · line 149
Quoted 5 lines
include/linux/entry-common.h +1
-1@@ -145,7 +146,7 @@ static __always_inline long syscall_enteunsigned long work =READ_ONCE (current_thread_info ()->syscall_work);if (work &SYSCALL_WORK_ENTER ) - syscall =syscall_trace_enter (regs, work); + syscall =syscall_trace_enter (regs, work, syscall);
Quoted 4 lines
include/linux/entry-common.h +0
-0return syscall; }
Re: [patch 10/18] entry: Use syscall number instead of rereading it
In reply to Thomas GleixnerQuoted 7 lines · Thomas Gleixner
rseq_syscall_enter_work()is invoked before the syscall number can be modified. So there is no point in rereading it frompt_regs.Signed-off-by Thomas Gleixner <[email protected]>--- include/linux/entry-common.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
Philippe Mathieu-Daudé
Reviewed-byRe: [patch 10/18] entry: Use syscall number instead of rereading it
Quoted 8 lines · Philippe Mathieu-Daudé
Quoted 7 lines · Thomas Gleixner
rseq_syscall_enter_work()is invoked before the syscall number can be modified. So there is no point in rereading it frompt_regs.Signed-off-by Thomas Gleixner <[email protected]>---
include/linux/entry-common.h| 9 +++++----1 file changed, 5 insertions(+), 4 deletions(-)
Re: [patch 10/18] entry: Use syscall number instead of rereading it
In reply to Thomas GleixnerQuoted 34 lines · Thomas Gleixner
rseq_syscall_enter_work()is invoked before the syscall number can be modified. So there is no point in rereading it frompt_regs.Signed-off-by Thomas Gleixner <[email protected]>--- include/linux/entry-common.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)include/linux/entry-common.h +4
-3@@ -70,9 +70,10 @@ static inline void syscall_enter_audit(s } } -static __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work) +static __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work, +long syscall) { -long syscall, ret =0 ; +long ret =0 ;/* * Handle Syscall User Dispatch. This must comes first, since @@ -90,7 +91,7 @@ static __always_inline long syscall_trac* through hrtimer_interrupt(). */ if (work &SYSCALL_WORK_SYSCALL_RSEQ_SLICE ) -rseq_syscall_enter_work (syscall_get_nr (current, regs)); +rseq_syscall_enter_work (syscall);/* Handle ptrace */ if (work & (SYSCALL_WORK_SYSCALL_TRACE |SYSCALL_WORK_SYSCALL_EMU )) {
include/linux/entry-common.h static __always_inline long syscall_ente · line 152
Quoted 8 lines
include/linux/entry-common.h +1
-1@@ -145,7 +146,7 @@ static __always_inline long syscall_enteunsigned long work =READ_ONCE (current_thread_info ()->syscall_work);if (work &SYSCALL_WORK_ENTER ) - syscall =syscall_trace_enter (regs, work); + syscall =syscall_trace_enter (regs, work, syscall);return syscall; }
[tip: core/entry] entry: Use syscall number instead of rereading it
In reply to Thomas GleixnerThe following commit has been merged into the core/entry branch of tip:
The following commit has been merged into the core/entry branch of tip:
Commit-ID: 8af25d0a2e465f3cb73c47c605fddd1664ee79b2 Gitweb: https://git.kernel.org/tip/8af25d0a2e465f3cb73c47c605fddd1664ee79b2 Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 07 Jul 2026 21:06:36 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Sun, 12 Jul 2026 12:38:01 +02:00
entry: Use syscall number instead of rereading it
rseq_syscall_enter_work() is invoked before the syscall number can be modified. So there is no point in rereading it from pt_regs.
--- include/linux/entry-common.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
include/linux/entry-common.h +5 -4
@@ -70,9 +70,10 @@ static inline void syscall_enter_audit(struct pt_regs *regs, long syscall) } } -static __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work) +static __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work, +long syscall) { -long syscall, ret =0 ; +long ret =0 ;/* * Handle Syscall User Dispatch. This must comes first, since
@@ -90,7 +91,7 @@ static __always_inline long syscall_trace_enter(struct pt_regs *regs, unsigned l* through hrtimer_interrupt(). */ if (work &SYSCALL_WORK_SYSCALL_RSEQ_SLICE ) -rseq_syscall_enter_work (syscall_get_nr (current, regs)); +rseq_syscall_enter_work (syscall);/* Handle ptrace */ if (work & (SYSCALL_WORK_SYSCALL_TRACE |SYSCALL_WORK_SYSCALL_EMU )) {
@@ -145,7 +146,7 @@ static __always_inline long syscall_enter_from_user_mode_work(struct pt_regs *reunsigned long work =READ_ONCE (current_thread_info ()->syscall_work);if (work &SYSCALL_WORK_ENTER ) - syscall =syscall_trace_enter (regs, work); + syscall =syscall_trace_enter (regs, work, syscall);return syscall; }
Thomas Gleixner
maintainerPATCH 11/18 seccomp, treewide: Rename and convert __secure_computing() to return boolean
In reply to Thomas GleixnerFrom: Jinjie Ruan <[email protected]>
The return value of __secure_computing() currently uses 0 to indicate that a system call should be allowed, and -1 to indicate that it should be blocked/killed. This 0/-1 pattern is non-intuitive for a security check function and makes the control flow at the call sites less readable.
Furthermore, any potential future changes to these return values would require a high-risk, error-prone audit of all its users across different architectures.
Sanitize this logic by converting the return type of __secure_computing() to a proper boolean, where 'true' explicitly means 'allow' and 'false' means 'fail/deny'.
Update all the two dozen or so call sites across the tree to align with this new boolean semantic. No functional changes are intended, as the callers still return -1 to the lower-level assembly entry code upon seccomp denial.
Rename the function to __seccomp_permit_syscall() so that the purpose is entirely clear.
[ tglx: Rename the function ]
--- arch/alpha/kernel/ptrace.c | 2 - arch/arm/kernel/ptrace.c | 2 - arch/arm64/kernel/ptrace.c | 2 - arch/csky/kernel/ptrace.c | 2 - arch/m68k/kernel/ptrace.c | 2 - arch/mips/kernel/ptrace.c | 2 - arch/parisc/kernel/ptrace.c | 2 - arch/sh/kernel/ptrace_32.c | 2 - arch/um/kernel/skas/syscall.c | 2 - arch/x86/entry/vsyscall/vsyscall_64.c | 14 ++++++------- arch/xtensa/kernel/ptrace.c | 3 -- include/linux/entry-common.h | 9 +++----- include/linux/seccomp.h | 12 +++++------ kernel/seccomp.c | 35 +++++++++++++++++----------------- 14 files changed, 45 insertions(+), 46 deletions(-)
arch/alpha/kernel/ptrace.c +1 -1
@@ -387,7 +387,7 @@ asmlinkage unsigned long syscall_trace_e* If this fails, seccomp may already have set up the return value * (e.g. SECCOMP_RET_ERRNO / TRACE). */ -if (secure_computing () ==-1 ) { +if (!seccomp_permit_syscall ()) {if (regs->r19 ==0 && regs->r0 == (unsigned long )-1 )syscall_set_return_value (current, regs, -ENOSYS ,0 );syscall_set_nr (current, regs,-1 );
arch/arm/kernel/ptrace.c +1 -1
@@ -855,7 +855,7 @@ asmlinkage int syscall_trace_enter(struc/* Do seccomp after ptrace; syscall may have changed. */ #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return -1 ;#else /* XXX: remove this once OABI gets fixed */
arch/arm64/kernel/ptrace.c +1 -1
@@ -2420,7 +2420,7 @@ int syscall_trace_enter(struct pt_regs * }/* Do the secure computing after ptrace; failures should be fast. */ -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return NO_SYSCALL ;if (test_thread_flag (TIF_SYSCALL_TRACEPOINT ))
arch/csky/kernel/ptrace.c +1 -1
@@ -323,7 +323,7 @@ asmlinkage int syscall_trace_enter(strucif (ptrace_report_syscall_entry (regs))return -1 ; -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return -1 ;if (test_thread_flag (TIF_SYSCALL_TRACEPOINT ))
arch/m68k/kernel/ptrace.c +1 -1
@@ -281,7 +281,7 @@ asmlinkage int syscall_trace_enter(void)if (test_thread_flag (TIF_SYSCALL_TRACE )) ret =ptrace_report_syscall_entry (task_pt_regs (current)); -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return -1 ;return ret;
arch/mips/kernel/ptrace.c +1 -1
@@ -1328,7 +1328,7 @@ asmlinkage long syscall_trace_enter(strureturn -1 ; } -if (secure_computing ()) +if (!seccomp_permit_syscall ())return -1 ;if (unlikely (test_thread_flag (TIF_SYSCALL_TRACEPOINT )))
arch/parisc/kernel/ptrace.c +1 -1
@@ -351,7 +351,7 @@ long do_syscall_trace_enter(struct pt_re }/* Do the secure computing check after ptrace. */ -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return -1 ;#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
arch/sh/kernel/ptrace_32.c +1 -1
@@ -460,7 +460,7 @@ asmlinkage long do_syscall_trace_enter(sreturn -1 ; } -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return -1 ;if (unlikely (test_thread_flag (TIF_SYSCALL_TRACEPOINT )))
arch/um/kernel/skas/syscall.c +1 -1
@@ -27,7 +27,7 @@ void handle_syscall(struct uml_pt_regs * goto out;/* Do the seccomp check after ptrace; failures should be fast. */ -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ()) goto out; syscall =UPT_SYSCALL_NR (r);
arch/x86/entry/vsyscall/vsyscall_64.c +7 -7
@@ -118,10 +118,10 @@ static bool write_ok_or_segv(unsigned lostatic bool __emulate_vsyscall (struct pt_regs *regs,unsigned long address) { -unsigned long caller; -int vsyscall_nr, syscall_nr, tmp; +unsigned long caller, orig_dx; +int vsyscall_nr, syscall_nr; +bool skip;long ret; -unsigned long orig_dx;/* Confirm that the fault happened in 64-bit user mode */ if (!user_64bit_mode (regs))
@@ -197,16 +197,16 @@ static bool __emulate_vsyscall(struct pt*/ regs->orig_ax = syscall_nr; regs->ax = -ENOSYS ; - tmp =secure_computing (); -if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) { + skip = !seccomp_permit_syscall (); +if ((!skip && regs->orig_ax != syscall_nr) || regs->ip != address) {warn_bad_vsyscall (KERN_DEBUG , regs,"seccomp tried to change syscall nr or ip" );force_exit_sig (SIGSYS );return true; } regs->orig_ax =-1 ; -if (tmp) - goto do_ret;/* skip requested */ +if (skip) + goto do_ret;/* * With a real vsyscall, page faults cause SIGSEGV.
arch/xtensa/kernel/ptrace.c +1 -2
@@ -553,8 +553,7 @@ int do_syscall_trace_enter(struct pt_regreturn 0 ; } -if (regs->syscall ==NO_SYSCALL || -secure_computing () ==-1 ) { +if (regs->syscall ==NO_SYSCALL || !seccomp_permit_syscall ()) {do_syscall_trace_leave (regs);return 0 ; }
include/linux/entry-common.h +4 -5
@@ -102,9 +102,8 @@ static __always_inline long syscall_trac/* Do seccomp after ptrace, to catch any tracer changes. */ if (work &SYSCALL_WORK_SECCOMP ) { - ret =__secure_computing (); -if (ret ==-1L ) -return ret; +if (!__seccomp_permit_syscall ()) +return -1L ; }/* Either of the above might have changed the syscall number */
@@ -115,7 +114,7 @@ static __always_inline long syscall_tracsyscall_enter_audit (regs, syscall); -return ret ? : syscall; +return syscall; }/**
@@ -138,7 +137,7 @@ static __always_inline long syscall_trac* It handles the following work items: * * 1) syscall_work flag dependent invocations of -* ptrace_report_syscall_entry(), __secure_computing(), trace_sys_enter() +* ptrace_report_syscall_entry(), __seccomp_permit_syscall(), trace_sys_enter() * 2) Invocation of audit_syscall_entry() */ static __always_inline long syscall_enter_from_user_mode_work (struct pt_regs *regs,long syscall)
include/linux/seccomp.h +6 -6
@@ -22,14 +22,14 @@#include <linux/atomic.h> #include <asm/seccomp.h> -extern int __secure_computing (void ); +extern bool __seccomp_permit_syscall (void );#ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER -static inline int secure_computing (void ) +static __always_inline bool seccomp_permit_syscall(void) {if (unlikely (test_syscall_work (SECCOMP ))) -return __secure_computing (); -return 0 ; +return __seccomp_permit_syscall (); +return true; }#else extern void secure_computing_strict (int this_syscall);
@@ -50,11 +50,11 @@ static inline int seccomp_mode(struct sestruct seccomp_data ;#ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER -static inline int secure_computing (void ) {return 0 ; } +static inline bool seccomp_permit_syscall (void ) {return true; }#else static inline void secure_computing_strict (int this_syscall) {return ; }#endif -static inline int __secure_computing (void ) {return 0 ; } +static inline bool __seccomp_permit_syscall (void ) {return true; }static inline long prctl_get_seccomp (void ) {
kernel/seccomp.c +18 -17
@@ -1100,12 +1100,13 @@ void secure_computing_strict(int this_sy else BUG(); } -int __secure_computing (void ) + +bool __seccomp_permit_syscall (void ) {int this_syscall =syscall_get_nr (current,current_pt_regs ());secure_computing_strict (this_syscall); -return 0 ; +return true; }#else
@@ -1256,7 +1257,7 @@ static int seccomp_do_user_notification(return -1 ; } -static int __seccomp_filter (int this_syscall,const bool recheck_after_trace) +static bool __seccomp_filter (int this_syscall,const bool recheck_after_trace) {u32 filter_ret, action;struct seccomp_data sd;
@@ -1294,7 +1295,7 @@ static int __seccomp_filter(int this_syscase SECCOMP_RET_TRACE :/* We've been put in this state by the ptracer already. */ if (recheck_after_trace) -return 0 ; +return true;/* ENOSYS these calls if there is no tracer attached. */ if (!ptrace_event_enabled (current,PTRACE_EVENT_SECCOMP )) {
@@ -1330,19 +1331,19 @@ static int __seccomp_filter(int this_sys* a skip would have already been reported. */ if (__seccomp_filter (this_syscall, true)) -return -1 ; +return false; -return 0 ; +return true;case SECCOMP_RET_USER_NOTIF :if (seccomp_do_user_notification (this_syscall, match, &sd)) goto skip; -return 0 ; +return true;case SECCOMP_RET_LOG :seccomp_log (this_syscall,0 , action, true); -return 0 ; +return true;case SECCOMP_RET_ALLOW :/*
@@ -1350,7 +1351,7 @@ static int __seccomp_filter(int this_sys* this action since SECCOMP_RET_ALLOW is the starting * state in seccomp_run_filters(). */ -return 0 ; +return true;case SECCOMP_RET_KILL_THREAD :case SECCOMP_RET_KILL_PROCESS :
@@ -1367,46 +1368,46 @@ static int __seccomp_filter(int this_sys } else {do_exit (SIGSYS ); } -return -1 ;/* skip the syscall go directly to signal handling */ +return false;/* skip the syscall go directly to signal handling */ }unreachable (); skip:seccomp_log (this_syscall,0 , action, match ? match->log : false); -return -1 ; +return false; }#else -static int __seccomp_filter (int this_syscall,const bool recheck_after_trace) +static bool __seccomp_filter (int this_syscall,const bool recheck_after_trace) {BUG (); -return -1 ; +return false; }#endif -int __secure_computing (void ) +bool __seccomp_permit_syscall (void ) {int mode = current->seccomp.mode;int this_syscall;if (IS_ENABLED (CONFIG_CHECKPOINT_RESTORE ) &&unlikely (current->ptrace &PT_SUSPEND_SECCOMP )) -return 0 ; +return true; this_syscall =syscall_get_nr (current,current_pt_regs ());switch (mode) {case SECCOMP_MODE_STRICT :__secure_computing_strict (this_syscall);/* may call do_exit */ -return 0 ; +return true;case SECCOMP_MODE_FILTER :return __seccomp_filter (this_syscall, false);/* Surviving SECCOMP_RET_KILL_* must be proactively impossible. */ case SECCOMP_MODE_DEAD :WARN_ON_ONCE (1 );do_exit (SIGKILL ); -return -1 ; +return false;default :BUG (); }
Re: [patch 11/18] seccomp, treewide: Rename and convert __secure_computing() to return boolean
Quoted 50 lines · Thomas Gleixner
From: Jinjie Ruan <[email protected]>
The return value of
__secure_computing()currently uses 0 to indicate that a system call should be allowed, and -1 to indicate that it should be blocked/killed. This 0/-1 pattern is non-intuitive for a security check function and makes the control flow at the call sites less readable.Furthermore, any potential future changes to these return values would require a high-risk, error-prone audit of all its users across different architectures.
Sanitize this logic by converting the return type of
__secure_computing()to a proper boolean, where 'true' explicitly means 'allow' and 'false' means 'fail/deny'.Update all the two dozen or so call sites across the tree to align with this new boolean semantic. No functional changes are intended, as the callers still return -1 to the lower-level assembly entry code upon seccomp denial.
Rename the function to
__seccomp_permit_syscall()so that the purpose is entirely clear.[ tglx: Rename the function ]
Suggested-by Thomas Gleixner <[email protected]>Suggested-by Mark Rutland <[email protected]>Signed-off-by Jinjie Ruan <[email protected]>Signed-off-by Thomas Gleixner <[email protected]>Cc Kees Cook <[email protected]>Cc Andy Lutomirski <[email protected]>Cc Oleg Nesterov <[email protected]>Cc Richard Henderson <[email protected]>Cc Russell King <[email protected]>Cc Catalin Marinas <[email protected]>Cc Guo Ren <[email protected]>Cc Geert Uytterhoeven <[email protected]>Cc Thomas Bogendoerfer <[email protected]>Cc Helge Deller <[email protected]>Cc Yoshinori Sato <[email protected]>Cc Richard Weinberger <[email protected]>Cc Chris Zankel <[email protected]>
Quoted 16 lines
--- arch/alpha/kernel/ptrace.c | 2 - arch/arm/kernel/ptrace.c | 2 - arch/arm64/kernel/ptrace.c | 2 - arch/csky/kernel/ptrace.c | 2 - arch/m68k/kernel/ptrace.c | 2 - arch/mips/kernel/ptrace.c | 2 - arch/parisc/kernel/ptrace.c | 2 - arch/sh/kernel/ptrace_32.c | 2 - arch/um/kernel/skas/syscall.c | 2 - arch/x86/entry/vsyscall/vsyscall_64.c | 14 ++++++------- arch/xtensa/kernel/ptrace.c | 3 -- include/linux/entry-common.h | 9 +++----- include/linux/seccomp.h | 12 +++++------ kernel/seccomp.c | 35 +++++++++++++++++----------------- 14 files changed, 45 insertions(+), 46 deletions(-)
As Ada pointed out, the description of secure_computing in arch/Kconfig need to be updated, a possible suggestion:
arch/Kconfig +0 -2
@@ -636,8 +636,8 @@ config HAVE_ARCH_SECCOMP_FILTER - syscall_rollback() - syscall_set_return_value() - SIGSYS siginfo_t support - - secure_computing is called from a ptrace_event()-safe context - - secure_computing return value is checked and a return value
of -1
+ - seccomp_permits_syscall is called from a ptrace_event()-safe
context
+ - seccomp_permits_syscall return value is checked and if false
Link:
https://lore.kernel.org/all/[email protected]/
Quoted 11 lines
arch/alpha/kernel/ptrace.c +1
-1@@ -387,7 +387,7 @@ asmlinkage unsigned long syscall_trace_e* If this fails, seccomp may already have set up the return value * (e.g. SECCOMP_RET_ERRNO / TRACE). */ -if (secure_computing () ==-1 ) { +if (!seccomp_permit_syscall ()) {if (regs->r19 ==0 && regs->r0 == (unsigned long )-1 )syscall_set_return_value (current, regs, -ENOSYS ,0 );syscall_set_nr (current, regs,-1 );
[...]
Quoted 15 lines
arch/alpha/kernel/ptrace.c +2
-2-static int __seccomp_filter (int this_syscall,const bool recheck_after_trace) +static bool __seccomp_filter (int this_syscall,const bool recheck_after_trace) {u32 filter_ret, action;struct seccomp_data sd;@@ -1294,7 +1295,7 @@ static int __seccomp_filter(int this_syscase SECCOMP_RET_TRACE :/* We've been put in this state by the ptracer already. */ if (recheck_after_trace) -return 0 ; +return true;/* ENOSYS these calls if there is no tracer attached. */ if (!ptrace_event_enabled (current,PTRACE_EVENT_SECCOMP )) {
arch/alpha/kernel/ptrace.c static int __seccomp_filter(int this_sys · line 1334
Quoted 5 lines
arch/alpha/kernel/ptrace.c +1
-1@@ -1330,19 +1331,19 @@ static int __seccomp_filter(int this_sys* a skip would have already been reported. */ if (__seccomp_filter (this_syscall, true)) -return -1 ; +return false;
The return value of __seccomp_filter is checked in the wrong way, check -1 should be replaced with check false, maybe:
- if (__seccomp_filter(this_syscall, true))
- return -1;
+ if (!__seccomp_filter(this_syscall, true))
+ return false;
otherwise,
LGTM
Quoted 83 lines
arch/alpha/kernel/ptrace.c +12
-12-return 0 ; +return true;case SECCOMP_RET_USER_NOTIF :if (seccomp_do_user_notification (this_syscall, match, &sd)) goto skip; -return 0 ; +return true;case SECCOMP_RET_LOG :seccomp_log (this_syscall,0 , action, true); -return 0 ; +return true;case SECCOMP_RET_ALLOW :/* @@ -1350,7 +1351,7 @@ static int __seccomp_filter(int this_sys* this action since SECCOMP_RET_ALLOW is the starting * state in seccomp_run_filters(). */ -return 0 ; +return true;case SECCOMP_RET_KILL_THREAD :case SECCOMP_RET_KILL_PROCESS :@@ -1367,46 +1368,46 @@ static int __seccomp_filter(int this_sys } else {do_exit (SIGSYS ); } -return -1 ;/* skip the syscall go directly to signal handling */ +return false;/* skip the syscall go directly to signal handling */ }unreachable (); skip:seccomp_log (this_syscall,0 , action, match ? match->log : false); -return -1 ; +return false; }#else -static int __seccomp_filter (int this_syscall,const bool recheck_after_trace) +static bool __seccomp_filter (int this_syscall,const bool recheck_after_trace) {BUG (); -return -1 ; +return false; }#endif -int __secure_computing (void ) +bool __seccomp_permit_syscall (void ) {int mode = current->seccomp.mode;int this_syscall;if (IS_ENABLED (CONFIG_CHECKPOINT_RESTORE ) &&unlikely (current->ptrace &PT_SUSPEND_SECCOMP )) -return 0 ; +return true; this_syscall =syscall_get_nr (current,current_pt_regs ());switch (mode) {case SECCOMP_MODE_STRICT :__secure_computing_strict (this_syscall);/* may call do_exit */ -return 0 ; +return true;case SECCOMP_MODE_FILTER :return __seccomp_filter (this_syscall, false);/* Surviving SECCOMP_RET_KILL_* must be proactively impossible. */ case SECCOMP_MODE_DEAD :WARN_ON_ONCE (1 );do_exit (SIGKILL ); -return -1 ; +return false;default :BUG (); }
Thomas Gleixner
maintainerRe: [patch 11/18] seccomp, treewide: Rename and convert __secure_computing() to return boolean
Quoted 12 lines · Jinjie Ruan
On 7/8/2026 3:06 AM, Thomas Gleixner wrote:
As Ada pointed out, the description ofsecure_computinginarch/Kconfigneed to be updated, a possible suggestion:arch/Kconfig +0
-2@@ -636,8 +636,8 @@ config HAVE_ARCH_SECCOMP_FILTER - syscall_rollback() - syscall_set_return_value() - SIGSYS siginfo_t support - - secure_computing is called from a ptrace_event()-safe context - - secure_computing return value is checked and a return value
Quoted 4 lines
of -1
+ -seccomp_permits_syscallis called from a ptrace_event()-safe
context
+ -seccomp_permits_syscallreturn value is checked and if false
Makes sense.
arch/Kconfig
Quoted 11 lines
Review
Quoted 3 lines
(quoted diff) +1
-1if (__seccomp_filter(this_syscall, true)) - return -1; + return false;The return value of
__seccomp_filteris checked in the wrong way, check -1 should be replaced with check false, maybe:arch/Kconfig +2
-2- if (__seccomp_filter(this_syscall, true)) - return -1; + if (!__seccomp_filter(this_syscall, true)) + return false;
Ooops.
Re: [patch 11/18] seccomp, treewide: Rename and convert __secure_computing() to return boolean
Quoted 10 lines · Thomas Gleixner
Review
Quoted 8 lines · Jinjie Ruan
The return value of
__seccomp_filteris checked in the wrong way, check -1 should be replaced with check false, maybe:(quoted diff) +2
-2- if (__seccomp_filter(this_syscall, true)) - return -1; + if (!__seccomp_filter(this_syscall, true)) + return false;
Or simply
return __seccomp_filter(this_syscall, true);
and remove "return true" below ?
Either way, I personally like this change, I was always confused by these -1's.
Thomas Gleixner
maintainerRe: [patch 11/18] seccomp, treewide: Rename and convert __secure_computing() to return boolean
Quoted 12 lines · Oleg Nesterov
Quoted 10 lines · Thomas Gleixner
Review
Quoted 8 lines · Jinjie Ruan
The return value of
__seccomp_filteris checked in the wrong way, check -1 should be replaced with check false, maybe:(quoted diff) +2
-2- if (__seccomp_filter(this_syscall, true)) - return -1; + if (!__seccomp_filter(this_syscall, true)) + return false;
Quoted 5 lines
Or simply
return __seccomp_filter(this_syscall, true);and remove "return true" below ?
Duh. Obvious now that you point it out :)
Quoted 1 line
Either way, I personally like this change, I was always confused by these -1's.
Welcome to the club!
Kees Cook
maintainerRe: [patch 11/18] seccomp, treewide: Rename and convert __secure_computing() to return boolean
In reply to Thomas GleixnerQuoted 6 lines · Thomas Gleixner
From: Jinjie Ruan <[email protected]>
The return value of
__secure_computing()currently uses 0 to indicate that a system call should be allowed, and -1 to indicate that it should be blocked/killed. This 0/-1 pattern is non-intuitive for a security check function and makes the control flow at the call sites less readable.
Conceptually, I'm good with this. Just make sure that the tools/testing/selftests/seccomp/seccomp_bpf tests still passes. :)
Signature · 1 line
Kees Cook
Re: [patch 11/18] seccomp, treewide: Rename and convert __secure_computing() to return boolean
In reply to Thomas GleixnerQuoted 396 lines · Thomas Gleixner
From: Jinjie Ruan <[email protected]>
The return value of
__secure_computing()currently uses 0 to indicate that a system call should be allowed, and -1 to indicate that it should be blocked/killed. This 0/-1 pattern is non-intuitive for a security check function and makes the control flow at the call sites less readable.Furthermore, any potential future changes to these return values would require a high-risk, error-prone audit of all its users across different architectures.
Sanitize this logic by converting the return type of
__secure_computing()to a proper boolean, where 'true' explicitly means 'allow' and 'false' means 'fail/deny'.Update all the two dozen or so call sites across the tree to align with this new boolean semantic. No functional changes are intended, as the callers still return -1 to the lower-level assembly entry code upon seccomp denial.
Rename the function to
__seccomp_permit_syscall()so that the purpose is entirely clear.[ tglx: Rename the function ]
Suggested-by Thomas Gleixner <[email protected]>Suggested-by Mark Rutland <[email protected]>Signed-off-by Jinjie Ruan <[email protected]>Signed-off-by Thomas Gleixner <[email protected]>Cc Kees Cook <[email protected]>Cc Andy Lutomirski <[email protected]>Cc Oleg Nesterov <[email protected]>Cc Richard Henderson <[email protected]>Cc Russell King <[email protected]>Cc Catalin Marinas <[email protected]>Cc Guo Ren <[email protected]>Cc Geert Uytterhoeven <[email protected]>Cc Thomas Bogendoerfer <[email protected]>Cc Helge Deller <[email protected]>Cc Yoshinori Sato <[email protected]>Cc Richard Weinberger <[email protected]>Cc Chris Zankel <[email protected]>--- arch/alpha/kernel/ptrace.c | 2 - arch/arm/kernel/ptrace.c | 2 - arch/arm64/kernel/ptrace.c | 2 - arch/csky/kernel/ptrace.c | 2 - arch/m68k/kernel/ptrace.c | 2 - arch/mips/kernel/ptrace.c | 2 - arch/parisc/kernel/ptrace.c | 2 - arch/sh/kernel/ptrace_32.c | 2 - arch/um/kernel/skas/syscall.c | 2 - arch/x86/entry/vsyscall/vsyscall_64.c | 14 ++++++------- arch/xtensa/kernel/ptrace.c | 3 -- include/linux/entry-common.h | 9 +++----- include/linux/seccomp.h | 12 +++++------ kernel/seccomp.c | 35 +++++++++++++++++----------------- 14 files changed, 45 insertions(+), 46 deletions(-)arch/alpha/kernel/ptrace.c +1
-1@@ -387,7 +387,7 @@ asmlinkage unsigned long syscall_trace_e* If this fails, seccomp may already have set up the return value * (e.g. SECCOMP_RET_ERRNO / TRACE). */ -if (secure_computing () ==-1 ) { +if (!seccomp_permit_syscall ()) {if (regs->r19 ==0 && regs->r0 == (unsigned long )-1 )syscall_set_return_value (current, regs, -ENOSYS ,0 );syscall_set_nr (current, regs,-1 );arch/arm/kernel/ptrace.c +1
-1@@ -855,7 +855,7 @@ asmlinkage int syscall_trace_enter(struc/* Do seccomp after ptrace; syscall may have changed. */ #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return -1 ;#else /* XXX: remove this once OABI gets fixed */ arch/arm64/kernel/ptrace.c +1
-1@@ -2420,7 +2420,7 @@ int syscall_trace_enter(struct pt_regs * }/* Do the secure computing after ptrace; failures should be fast. */ -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return NO_SYSCALL ;if (test_thread_flag (TIF_SYSCALL_TRACEPOINT ))arch/csky/kernel/ptrace.c +1
-1@@ -323,7 +323,7 @@ asmlinkage int syscall_trace_enter(strucif (ptrace_report_syscall_entry (regs))return -1 ; -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return -1 ;if (test_thread_flag (TIF_SYSCALL_TRACEPOINT ))arch/m68k/kernel/ptrace.c +1
-1@@ -281,7 +281,7 @@ asmlinkage int syscall_trace_enter(void)if (test_thread_flag (TIF_SYSCALL_TRACE )) ret =ptrace_report_syscall_entry (task_pt_regs (current)); -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return -1 ;return ret;arch/mips/kernel/ptrace.c +1
-1@@ -1328,7 +1328,7 @@ asmlinkage long syscall_trace_enter(strureturn -1 ; } -if (secure_computing ()) +if (!seccomp_permit_syscall ())return -1 ;if (unlikely (test_thread_flag (TIF_SYSCALL_TRACEPOINT )))arch/parisc/kernel/ptrace.c +1
-1@@ -351,7 +351,7 @@ long do_syscall_trace_enter(struct pt_re }/* Do the secure computing check after ptrace. */ -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return -1 ;#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS arch/sh/kernel/ptrace_32.c +1
-1@@ -460,7 +460,7 @@ asmlinkage long do_syscall_trace_enter(sreturn -1 ; } -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return -1 ;if (unlikely (test_thread_flag (TIF_SYSCALL_TRACEPOINT )))arch/um/kernel/skas/syscall.c +1
-1@@ -27,7 +27,7 @@ void handle_syscall(struct uml_pt_regs * goto out;/* Do the seccomp check after ptrace; failures should be fast. */ -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ()) goto out; syscall =UPT_SYSCALL_NR (r);arch/x86/entry/vsyscall/vsyscall_64.c +7
-7@@ -118,10 +118,10 @@ static bool write_ok_or_segv(unsigned lostatic bool __emulate_vsyscall (struct pt_regs *regs,unsigned long address) { -unsigned long caller; -int vsyscall_nr, syscall_nr, tmp; +unsigned long caller, orig_dx; +int vsyscall_nr, syscall_nr; +bool skip;long ret; -unsigned long orig_dx;/* Confirm that the fault happened in 64-bit user mode */ if (!user_64bit_mode (regs))@@ -197,16 +197,16 @@ static bool __emulate_vsyscall(struct pt*/ regs->orig_ax = syscall_nr; regs->ax = -ENOSYS ; - tmp =secure_computing (); -if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) { + skip = !seccomp_permit_syscall (); +if ((!skip && regs->orig_ax != syscall_nr) || regs->ip != address) {warn_bad_vsyscall (KERN_DEBUG , regs,"seccomp tried to change syscall nr or ip" );force_exit_sig (SIGSYS );return true; } regs->orig_ax =-1 ; -if (tmp) - goto do_ret;/* skip requested */ +if (skip) + goto do_ret;/* * With a real vsyscall, page faults cause SIGSEGV. arch/xtensa/kernel/ptrace.c +1
-2@@ -553,8 +553,7 @@ int do_syscall_trace_enter(struct pt_regreturn 0 ; } -if (regs->syscall ==NO_SYSCALL || -secure_computing () ==-1 ) { +if (regs->syscall ==NO_SYSCALL || !seccomp_permit_syscall ()) {do_syscall_trace_leave (regs);return 0 ; }include/linux/entry-common.h +4
-5@@ -102,9 +102,8 @@ static __always_inline long syscall_trac/* Do seccomp after ptrace, to catch any tracer changes. */ if (work &SYSCALL_WORK_SECCOMP ) { - ret =__secure_computing (); -if (ret ==-1L ) -return ret; +if (!__seccomp_permit_syscall ()) +return -1L ; }/* Either of the above might have changed the syscall number */ @@ -115,7 +114,7 @@ static __always_inline long syscall_tracsyscall_enter_audit (regs, syscall); -return ret ? : syscall; +return syscall; }/** @@ -138,7 +137,7 @@ static __always_inline long syscall_trac* It handles the following work items: * * 1) syscall_work flag dependent invocations of -* ptrace_report_syscall_entry(), __secure_computing(), trace_sys_enter() +* ptrace_report_syscall_entry(), __seccomp_permit_syscall(), trace_sys_enter() * 2) Invocation of audit_syscall_entry() */ static __always_inline long syscall_enter_from_user_mode_work (struct pt_regs *regs,long syscall)include/linux/seccomp.h +6
-6@@ -22,14 +22,14 @@#include <linux/atomic.h> #include <asm/seccomp.h> -extern int __secure_computing (void ); +extern bool __seccomp_permit_syscall (void );#ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER -static inline int secure_computing (void ) +static __always_inline bool seccomp_permit_syscall(void) {if (unlikely (test_syscall_work (SECCOMP ))) -return __secure_computing (); -return 0 ; +return __seccomp_permit_syscall (); +return true; }#else extern void secure_computing_strict (int this_syscall);@@ -50,11 +50,11 @@ static inline int seccomp_mode(struct sestruct seccomp_data ;#ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER -static inline int secure_computing (void ) {return 0 ; } +static inline bool seccomp_permit_syscall (void ) {return true; }#else static inline void secure_computing_strict (int this_syscall) {return ; }#endif -static inline int __secure_computing (void ) {return 0 ; } +static inline bool __seccomp_permit_syscall (void ) {return true; }static inline long prctl_get_seccomp (void ) {kernel/seccomp.c +17
-16@@ -1100,12 +1100,13 @@ void secure_computing_strict(int this_sy else BUG(); } -int __secure_computing (void ) + +bool __seccomp_permit_syscall (void ) {int this_syscall =syscall_get_nr (current,current_pt_regs ());secure_computing_strict (this_syscall); -return 0 ; +return true; }#else @@ -1256,7 +1257,7 @@ static int seccomp_do_user_notification(return -1 ; } -static int __seccomp_filter (int this_syscall,const bool recheck_after_trace) +static bool __seccomp_filter (int this_syscall,const bool recheck_after_trace) {u32 filter_ret, action;struct seccomp_data sd;@@ -1294,7 +1295,7 @@ static int __seccomp_filter(int this_syscase SECCOMP_RET_TRACE :/* We've been put in this state by the ptracer already. */ if (recheck_after_trace) -return 0 ; +return true;/* ENOSYS these calls if there is no tracer attached. */ if (!ptrace_event_enabled (current,PTRACE_EVENT_SECCOMP )) {@@ -1330,19 +1331,19 @@ static int __seccomp_filter(int this_sys* a skip would have already been reported. */ if (__seccomp_filter (this_syscall, true)) -return -1 ; +return false; -return 0 ; +return true;case SECCOMP_RET_USER_NOTIF :if (seccomp_do_user_notification (this_syscall, match, &sd)) goto skip; -return 0 ; +return true;case SECCOMP_RET_LOG :seccomp_log (this_syscall,0 , action, true); -return 0 ; +return true;case SECCOMP_RET_ALLOW :/* @@ -1350,7 +1351,7 @@ static int __seccomp_filter(int this_sys* this action since SECCOMP_RET_ALLOW is the starting * state in seccomp_run_filters(). */ -return 0 ; +return true;case SECCOMP_RET_KILL_THREAD :case SECCOMP_RET_KILL_PROCESS :@@ -1367,46 +1368,46 @@ static int __seccomp_filter(int this_sys } else {do_exit (SIGSYS ); } -return -1 ;/* skip the syscall go directly to signal handling */ +return false;/* skip the syscall go directly to signal handling */ }unreachable (); skip:seccomp_log (this_syscall,0 , action, match ? match->log : false); -return -1 ; +return false; }#else -static int __seccomp_filter (int this_syscall,const bool recheck_after_trace) +static bool __seccomp_filter (int this_syscall,const bool recheck_after_trace) {BUG (); -return -1 ; +return false; }#endif -int __secure_computing (void ) +bool __seccomp_permit_syscall (void ) {int mode = current->seccomp.mode;int this_syscall;if (IS_ENABLED (CONFIG_CHECKPOINT_RESTORE ) &&unlikely (current->ptrace &PT_SUSPEND_SECCOMP )) -return 0 ; +return true; this_syscall =syscall_get_nr (current,current_pt_regs ());switch (mode) {case SECCOMP_MODE_STRICT :__secure_computing_strict (this_syscall);/* may call do_exit */ -return 0 ; +return true;case SECCOMP_MODE_FILTER :
kernel/seccomp.c static int __seccomp_filter(int this_sys · line 1413
Quoted 10 lines
kernel/seccomp.c +1
-1return __seccomp_filter (this_syscall, false);/* Surviving SECCOMP_RET_KILL_* must be proactively impossible. */ case SECCOMP_MODE_DEAD :WARN_ON_ONCE (1 );do_exit (SIGKILL ); -return -1 ; +return false;default :BUG (); }
[tip: core/entry] seccomp, treewide: Rename and convert __secure_computing() to return boolean
In reply to Thomas GleixnerThe following commit has been merged into the core/entry branch of tip:
The following commit has been merged into the core/entry branch of tip:
Commit-ID: 7ba2ba74713c83408cc942b60dd869ab2c34c84f Gitweb: https://git.kernel.org/tip/7ba2ba74713c83408cc942b60dd869ab2c34c84f Author: Jinjie Ruan <[email protected]> AuthorDate: Tue, 07 Jul 2026 21:06:40 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Sun, 12 Jul 2026 12:38:02 +02:00
seccomp, treewide: Rename and convert __secure_computing() to return boolean
The return value of __secure_computing() currently uses 0 to indicate that a system call should be allowed, and -1 to indicate that it should be blocked/killed. This 0/-1 pattern is non-intuitive for a security check function and makes the control flow at the call sites less readable.
Furthermore, any potential future changes to these return values would require a high-risk, error-prone audit of all its users across different architectures.
Sanitize this logic by converting the return type of __secure_computing() to a proper boolean, where 'true' explicitly means 'allow' and 'false' means 'fail/deny'.
Update all the two dozen or so call sites across the tree to align with this new boolean semantic. No functional changes are intended, as the callers still return -1 to the lower-level assembly entry code upon seccomp denial.
Rename the function to __seccomp_permit_syscall() so that the purpose is entirely clear.
[ tglx: Rename the function ]
--- arch/Kconfig | 2 +- arch/alpha/kernel/ptrace.c | 2 +- arch/arm/kernel/ptrace.c | 2 +- arch/arm64/kernel/ptrace.c | 2 +- arch/csky/kernel/ptrace.c | 2 +- arch/m68k/kernel/ptrace.c | 2 +- arch/mips/kernel/ptrace.c | 2 +- arch/parisc/kernel/ptrace.c | 2 +- arch/sh/kernel/ptrace_32.c | 2 +- arch/um/kernel/skas/syscall.c | 2 +- arch/x86/entry/vsyscall/vsyscall_64.c | 14 +++++----- arch/xtensa/kernel/ptrace.c | 3 +-- include/linux/entry-common.h | 9 +++---- include/linux/seccomp.h | 12 ++++----- kernel/seccomp.c | 36 ++++++++++++-------------- 15 files changed, 45 insertions(+), 49 deletions(-)
arch/Kconfig +1 -1
@@ -647,7 +647,7 @@ config HAVE_ARCH_SECCOMP_FILTER - syscall_set_return_value() - SIGSYS siginfo_t support - secure_computing is called from a ptrace_event()-safe context - - secure_computing return value is checked and a return value of -1 + - secure_computing return value is checked and if false it results in the system call being skipped immediately. - seccomp syscall wired up - if !HAVE_SPARSE_SYSCALL_NR, have SECCOMP_ARCH_NATIVE,
arch/alpha/kernel/ptrace.c +1 -1
@@ -387,7 +387,7 @@ asmlinkage unsigned long syscall_trace_enter(void)* If this fails, seccomp may already have set up the return value * (e.g. SECCOMP_RET_ERRNO / TRACE). */ -if (secure_computing () ==-1 ) { +if (!seccomp_permit_syscall ()) {if (regs->r19 ==0 && regs->r0 == (unsigned long )-1 )syscall_set_return_value (current, regs, -ENOSYS ,0 );syscall_set_nr (current, regs,-1 );
arch/arm/kernel/ptrace.c +1 -1
@@ -855,7 +855,7 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)/* Do seccomp after ptrace; syscall may have changed. */ #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return -1 ;#else /* XXX: remove this once OABI gets fixed */
arch/arm64/kernel/ptrace.c +1 -1
@@ -2420,7 +2420,7 @@ int syscall_trace_enter(struct pt_regs *regs) }/* Do the secure computing after ptrace; failures should be fast. */ -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return NO_SYSCALL ;if (test_thread_flag (TIF_SYSCALL_TRACEPOINT ))
arch/csky/kernel/ptrace.c +1 -1
@@ -323,7 +323,7 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)if (ptrace_report_syscall_entry (regs))return -1 ; -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return -1 ;if (test_thread_flag (TIF_SYSCALL_TRACEPOINT ))
arch/m68k/kernel/ptrace.c +1 -1
@@ -281,7 +281,7 @@ asmlinkage int syscall_trace_enter(void)if (test_thread_flag (TIF_SYSCALL_TRACE )) ret =ptrace_report_syscall_entry (task_pt_regs (current)); -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return -1 ;return ret;
arch/mips/kernel/ptrace.c +1 -1
@@ -1328,7 +1328,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs)return -1 ; } -if (secure_computing ()) +if (!seccomp_permit_syscall ())return -1 ;if (unlikely (test_thread_flag (TIF_SYSCALL_TRACEPOINT )))
arch/parisc/kernel/ptrace.c +1 -1
@@ -351,7 +351,7 @@ long do_syscall_trace_enter(struct pt_regs *regs) }/* Do the secure computing check after ptrace. */ -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return -1 ;#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
arch/sh/kernel/ptrace_32.c +1 -1
@@ -460,7 +460,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)return -1 ; } -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ())return -1 ;if (unlikely (test_thread_flag (TIF_SYSCALL_TRACEPOINT )))
arch/um/kernel/skas/syscall.c +1 -1
@@ -27,7 +27,7 @@ void handle_syscall(struct uml_pt_regs *r) goto out;/* Do the seccomp check after ptrace; failures should be fast. */ -if (secure_computing () ==-1 ) +if (!seccomp_permit_syscall ()) goto out; syscall =UPT_SYSCALL_NR (r);
arch/x86/entry/vsyscall/vsyscall_64.c +7 -7
@@ -118,10 +118,10 @@ static bool write_ok_or_segv(unsigned long ptr, size_t size)static bool __emulate_vsyscall (struct pt_regs *regs,unsigned long address) { -unsigned long caller; -int vsyscall_nr, syscall_nr, tmp; +unsigned long caller, orig_dx; +int vsyscall_nr, syscall_nr; +bool skip;long ret; -unsigned long orig_dx;/* Confirm that the fault happened in 64-bit user mode */ if (!user_64bit_mode (regs))
@@ -197,16 +197,16 @@ static bool __emulate_vsyscall(struct pt_regs *regs, unsigned long address)*/ regs->orig_ax = syscall_nr; regs->ax = -ENOSYS ; - tmp =secure_computing (); -if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) { + skip = !seccomp_permit_syscall (); +if ((!skip && regs->orig_ax != syscall_nr) || regs->ip != address) {warn_bad_vsyscall (KERN_DEBUG , regs,"seccomp tried to change syscall nr or ip" );force_exit_sig (SIGSYS );return true; } regs->orig_ax =-1 ; -if (tmp) - goto do_ret;/* skip requested */ +if (skip) + goto do_ret;/* * With a real vsyscall, page faults cause SIGSEGV.
arch/xtensa/kernel/ptrace.c +1 -2
@@ -553,8 +553,7 @@ int do_syscall_trace_enter(struct pt_regs *regs)return 0 ; } -if (regs->syscall ==NO_SYSCALL || -secure_computing () ==-1 ) { +if (regs->syscall ==NO_SYSCALL || !seccomp_permit_syscall ()) {do_syscall_trace_leave (regs);return 0 ; }
include/linux/entry-common.h +4 -5
@@ -102,9 +102,8 @@ static __always_inline long syscall_trace_enter(struct pt_regs *regs, unsigned l/* Do seccomp after ptrace, to catch any tracer changes. */ if (work &SYSCALL_WORK_SECCOMP ) { - ret =__secure_computing (); -if (ret ==-1L ) -return ret; +if (!__seccomp_permit_syscall ()) +return -1L ; }/* Either of the above might have changed the syscall number */
@@ -115,7 +114,7 @@ static __always_inline long syscall_trace_enter(struct pt_regs *regs, unsigned lsyscall_enter_audit (regs, syscall); -return ret ? : syscall; +return syscall; }/**
@@ -138,7 +137,7 @@ static __always_inline long syscall_trace_enter(struct pt_regs *regs, unsigned l* It handles the following work items: * * 1) syscall_work flag dependent invocations of -* ptrace_report_syscall_entry(), __secure_computing(), trace_sys_enter() +* ptrace_report_syscall_entry(), __seccomp_permit_syscall(), trace_sys_enter() * 2) Invocation of audit_syscall_entry() */ static __always_inline long syscall_enter_from_user_mode_work (struct pt_regs *regs,long syscall)
include/linux/seccomp.h +6 -6
@@ -22,14 +22,14 @@#include <linux/atomic.h> #include <asm/seccomp.h> -extern int __secure_computing (void ); +extern bool __seccomp_permit_syscall (void );#ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER -static inline int secure_computing (void ) +static __always_inline bool seccomp_permit_syscall(void) {if (unlikely (test_syscall_work (SECCOMP ))) -return __secure_computing (); -return 0 ; +return __seccomp_permit_syscall (); +return true; }#else extern void secure_computing_strict (int this_syscall);
@@ -50,11 +50,11 @@ static inline int seccomp_mode(struct seccomp *s)struct seccomp_data ;#ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER -static inline int secure_computing (void ) {return 0 ; } +static inline bool seccomp_permit_syscall (void ) {return true; }#else static inline void secure_computing_strict (int this_syscall) {return ; }#endif -static inline int __secure_computing (void ) {return 0 ; } +static inline bool __seccomp_permit_syscall (void ) {return true; }static inline long prctl_get_seccomp (void ) {
kernel/seccomp.c +17 -19
@@ -1100,12 +1100,13 @@ void secure_computing_strict(int this_syscall) else BUG(); } -int __secure_computing (void ) + +bool __seccomp_permit_syscall (void ) {int this_syscall =syscall_get_nr (current,current_pt_regs ());secure_computing_strict (this_syscall); -return 0 ; +return true; }#else
@@ -1256,7 +1257,7 @@ out:return -1 ; } -static int __seccomp_filter (int this_syscall,const bool recheck_after_trace) +static bool __seccomp_filter (int this_syscall,const bool recheck_after_trace) {u32 filter_ret, action;struct seccomp_data sd;
@@ -1294,7 +1295,7 @@ static int __seccomp_filter(int this_syscall, const bool recheck_after_trace)case SECCOMP_RET_TRACE :/* We've been put in this state by the ptracer already. */ if (recheck_after_trace) -return 0 ; +return true;/* ENOSYS these calls if there is no tracer attached. */ if (!ptrace_event_enabled (current,PTRACE_EVENT_SECCOMP )) {
@@ -1329,20 +1330,17 @@ static int __seccomp_filter(int this_syscall, const bool recheck_after_trace)* a reload of all registers. This does not goto skip since * a skip would have already been reported. */ -if (__seccomp_filter (this_syscall, true)) -return -1 ; - -return 0 ; +return __seccomp_filter (this_syscall, true);case SECCOMP_RET_USER_NOTIF :if (seccomp_do_user_notification (this_syscall, match, &sd)) goto skip; -return 0 ; +return true;case SECCOMP_RET_LOG :seccomp_log (this_syscall,0 , action, true); -return 0 ; +return true;case SECCOMP_RET_ALLOW :/*
@@ -1350,7 +1348,7 @@ static int __seccomp_filter(int this_syscall, const bool recheck_after_trace)* this action since SECCOMP_RET_ALLOW is the starting * state in seccomp_run_filters(). */ -return 0 ; +return true;case SECCOMP_RET_KILL_THREAD :case SECCOMP_RET_KILL_PROCESS :
@@ -1367,46 +1365,46 @@ static int __seccomp_filter(int this_syscall, const bool recheck_after_trace) } else {do_exit (SIGSYS ); } -return -1 ;/* skip the syscall go directly to signal handling */ +return false;/* skip the syscall go directly to signal handling */ }unreachable (); skip:seccomp_log (this_syscall,0 , action, match ? match->log : false); -return -1 ; +return false; }#else -static int __seccomp_filter (int this_syscall,const bool recheck_after_trace) +static bool __seccomp_filter (int this_syscall,const bool recheck_after_trace) {BUG (); -return -1 ; +return false; }#endif -int __secure_computing (void ) +bool __seccomp_permit_syscall (void ) {int mode = current->seccomp.mode;int this_syscall;if (IS_ENABLED (CONFIG_CHECKPOINT_RESTORE ) &&unlikely (current->ptrace &PT_SUSPEND_SECCOMP )) -return 0 ; +return true; this_syscall =syscall_get_nr (current,current_pt_regs ());switch (mode) {case SECCOMP_MODE_STRICT :__secure_computing_strict (this_syscall);/* may call do_exit */ -return 0 ; +return true;case SECCOMP_MODE_FILTER :return __seccomp_filter (this_syscall, false);/* Surviving SECCOMP_RET_KILL_* must be proactively impossible. */ case SECCOMP_MODE_DEAD :WARN_ON_ONCE (1 );do_exit (SIGKILL ); -return -1 ; +return false;default :BUG (); }
Thomas Gleixner
maintainerPATCH 12/18 ptrace, treewide: Rename ptrace_report_syscall_entry() to ptrace_report_syscall_permit_entry()
In reply to Thomas GleixnerThe return value of that function is boolean and tells the caller whether to permit the syscall processing or not.
Rename the function so the purpose is clear and make the return type bool.
--- arch/alpha/kernel/ptrace.c | 2 +- arch/arc/kernel/ptrace.c | 2 +- arch/arm/kernel/ptrace.c | 2 +- arch/arm64/kernel/ptrace.c | 2 +- arch/csky/kernel/ptrace.c | 2 +- arch/hexagon/kernel/traps.c | 2 +- arch/m68k/kernel/ptrace.c | 2 +- arch/microblaze/kernel/ptrace.c | 2 +- arch/mips/kernel/ptrace.c | 2 +- arch/nios2/kernel/ptrace.c | 2 +- arch/openrisc/kernel/ptrace.c | 2 +- arch/parisc/kernel/ptrace.c | 10 ++++------ arch/sh/kernel/ptrace_32.c | 2 +- arch/sparc/kernel/ptrace_32.c | 2 +- arch/sparc/kernel/ptrace_64.c | 2 +- arch/um/kernel/ptrace.c | 2 +- arch/xtensa/kernel/ptrace.c | 2 +- include/asm-generic/syscall.h | 4 ++-- include/linux/entry-common.h | 25 ++++++++++++------------- include/linux/ptrace.h | 13 ++++++------- 20 files changed, 40 insertions(+), 44 deletions(-)
arch/alpha/kernel/ptrace.c +1 -1
@@ -375,7 +375,7 @@ asmlinkage unsigned long syscall_trace_estruct pt_regs *regs =current_pt_regs ();if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) { + !ptrace_report_syscall_permit_entry (regs)) {syscall_set_nr (current, regs,-1 );if (regs->r19 ==0 && regs->r0 == (unsigned long )-1 )syscall_set_return_value (current, regs, -ENOSYS ,0 );
arch/arc/kernel/ptrace.c +1 -1
@@ -342,7 +342,7 @@ long arch_ptrace(struct task_struct *chi asmlinkage int syscall_trace_enter(struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE )) -if (ptrace_report_syscall_entry (regs)) +if (!ptrace_report_syscall_permit_entry (regs))return ULONG_MAX ;#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
arch/arm/kernel/ptrace.c +1 -1
@@ -840,7 +840,7 @@ static void report_syscall(struct pt_regif (dir ==PTRACE_SYSCALL_EXIT )ptrace_report_syscall_exit (regs,0 ); -else if (ptrace_report_syscall_entry (regs)) +else if (!ptrace_report_syscall_permit_entry (regs))current_thread_info ()->abi_syscall =-1 ; regs->ARM_ip = ip;
arch/arm64/kernel/ptrace.c +1 -1
@@ -2379,7 +2379,7 @@ static int report_syscall_entry(struct pint regno, ret; saved_reg =ptrace_save_reg (regs,PTRACE_SYSCALL_ENTER , ®no); - ret =ptrace_report_syscall_entry (regs); + ret = !ptrace_report_syscall_permit_entry (regs);if (ret)forget_syscall (regs); regs->regs[regno] = saved_reg;
arch/csky/kernel/ptrace.c +1 -1
@@ -320,7 +320,7 @@ long arch_ptrace(struct task_struct *chi asmlinkage int syscall_trace_enter(struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE )) -if (ptrace_report_syscall_entry (regs)) +if (!ptrace_report_syscall_permit_entry (regs))return -1 ;if (!seccomp_permit_syscall ())
arch/hexagon/kernel/traps.c +1 -1
@@ -345,7 +345,7 @@ void do_trap0(struct pt_regs *regs)/* allow strace to catch syscall args */ if (unlikely (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs))) + !ptrace_report_syscall_permit_entry (regs)))return ;/* return -ENOSYS somewhere? */ /* Interrupts should be re-enabled for syscall processing */
arch/m68k/kernel/ptrace.c +1 -1
@@ -279,7 +279,7 @@ asmlinkage int syscall_trace_enter(void)int ret =0 ;if (test_thread_flag (TIF_SYSCALL_TRACE )) - ret =ptrace_report_syscall_entry (task_pt_regs (current)); + ret = !ptrace_report_syscall_permit_entry (task_pt_regs (current));if (!seccomp_permit_syscall ())return -1 ;
arch/microblaze/kernel/ptrace.c +1 -1
@@ -139,7 +139,7 @@ asmlinkage unsigned long do_syscall_tracsecure_computing_strict (regs->r12);if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) + !ptrace_report_syscall_permit_entry (regs))/* * Tracing decided this syscall should not happen. * We'll return a bogus call number to get an ENOSYS
arch/mips/kernel/ptrace.c +1 -1
@@ -1324,7 +1324,7 @@ asmlinkage long syscall_trace_enter(struuser_exit ();if (test_thread_flag (TIF_SYSCALL_TRACE )) { -if (ptrace_report_syscall_entry (regs)) +if (!ptrace_report_syscall_permit_entry (regs))return -1 ; }
arch/nios2/kernel/ptrace.c +1 -1
@@ -133,7 +133,7 @@ asmlinkage int do_syscall_trace_enter(voint ret =0 ;if (test_thread_flag (TIF_SYSCALL_TRACE )) - ret =ptrace_report_syscall_entry (task_pt_regs (current)); + ret = !ptrace_report_syscall_permit_entry (task_pt_regs (current));return ret; }
arch/openrisc/kernel/ptrace.c +1 -1
@@ -293,7 +293,7 @@ asmlinkage long do_syscall_trace_enter(slong ret =0 ;if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) + !ptrace_report_syscall_permit_entry (regs))/* * Tracing decided this syscall should not happen. * We'll return a bogus call number to get an ENOSYS
arch/parisc/kernel/ptrace.c +4 -6
@@ -326,7 +326,7 @@ long compat_arch_ptrace(struct task_strulong do_syscall_trace_enter (struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE )) { -int rc =ptrace_report_syscall_entry (regs); +bool permit =ptrace_report_syscall_permit_entry (regs);/* * As tracesys_next does not set %r28 to -ENOSYS
@@ -334,12 +334,10 @@ long do_syscall_trace_enter(struct pt_re*/ regs->gr[28 ] = -ENOSYS ; -if (rc) { +if (!permit) {/* -* A nonzero return code from -* ptrace_report_syscall_entry() tells us -* to prevent the syscall execution. Skip -* the syscall call and the syscall restart handling. +* Skip the syscall call and the syscall restart +* handling. * * Note that the tracer may also just change * regs->gr[20] to an invalid syscall number,
arch/sh/kernel/ptrace_32.c +1 -1
@@ -455,7 +455,7 @@ long arch_ptrace(struct task_struct *chiasmlinkage long do_syscall_trace_enter (struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) { + !ptrace_report_syscall_permit_entry (regs)) { regs->regs[0 ] = -ENOSYS ;return -1 ; }
arch/sparc/kernel/ptrace_32.c +1 -1
@@ -441,7 +441,7 @@ asmlinkage int syscall_trace(struct pt_rif (syscall_exit_p)ptrace_report_syscall_exit (regs,0 );else - ret =ptrace_report_syscall_entry (regs); + ret = !ptrace_report_syscall_permit_entry (regs); }return ret;
arch/sparc/kernel/ptrace_64.c +1 -1
@@ -1093,7 +1093,7 @@ asmlinkage int syscall_trace_enter(strucuser_exit ();if (test_thread_flag (TIF_SYSCALL_TRACE )) - ret =ptrace_report_syscall_entry (regs); + ret = !ptrace_report_syscall_permit_entry (regs);if (unlikely (test_thread_flag (TIF_SYSCALL_TRACEPOINT )))trace_sys_enter (regs, regs->u_regs[UREG_G1 ]);
arch/um/kernel/ptrace.c +1 -1
@@ -135,7 +135,7 @@ int syscall_trace_enter(struct pt_regs *if (!test_thread_flag (TIF_SYSCALL_TRACE ))return 0 ; -return ptrace_report_syscall_entry (regs); +return !ptrace_report_syscall_permit_entry (regs); }void syscall_trace_leave (struct pt_regs *regs)
arch/xtensa/kernel/ptrace.c +1 -1
@@ -547,7 +547,7 @@ int do_syscall_trace_enter(struct pt_reg regs->areg[2 ] = -ENOSYS ;if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) { + !ptrace_report_syscall_permit_entry (regs)) { regs->areg[2 ] = -ENOSYS ; regs->syscall =NO_SYSCALL ;return 0 ;
include/asm-generic/syscall.h +2 -2
@@ -58,8 +58,8 @@ void syscall_set_nr(struct task_struct ** * It's only valid to call this when @task is stopped for system * call exit tracing (due to %SYSCALL_WORK_SYSCALL_TRACE or -* %SYSCALL_WORK_SYSCALL_AUDIT), after ptrace_report_syscall_entry() -* returned nonzero to prevent the system call from taking place. +* %SYSCALL_WORK_SYSCALL_AUDIT), after ptrace_report_syscall_permit_entry() +* returned False to prevent the system call from taking place. * * This rolls back the register state in @regs so it's as if the * system call instruction was a no-op. The registers containing
include/linux/entry-common.h +12 -13
@@ -38,21 +38,22 @@ SYSCALL_WORK_SYSCALL_EXIT_TRAP)/** -* arch_ptrace_report_syscall_entry - Architecture specific ptrace_report_syscall_entry() wrapper +* arch_ptrace_report_syscall_permit_entry - Architecture specific wrapper for +* ptrace_report_syscall_permit_entry() * @regs: Pointer to the register state at syscall entry * -* Invoked from syscall_trace_enter() to wrap ptrace_report_syscall_entry(). +* Invoked from syscall_trace_enter() to wrap ptrace_report_syscall_permit_entry(). * -* This allows architecture specific ptrace_report_syscall_entry() +* This allows architecture specific ptrace_report_syscall_permit_entry() * implementations. If not defined by the architecture this falls back to -* to ptrace_report_syscall_entry(). +* to ptrace_report_syscall_permit_entry(). */ -static __always_inline int arch_ptrace_report_syscall_entry(struct pt_regs *regs); +static __always_inline bool arch_ptrace_report_syscall_permit_entry(struct pt_regs *regs); -#ifndef arch_ptrace_report_syscall_entry -static __always_inline int arch_ptrace_report_syscall_entry(struct pt_regs *regs) +#ifndef arch_ptrace_report_syscall_permit_entry +static __always_inline bool arch_ptrace_report_syscall_permit_entry(struct pt_regs *regs) { -return ptrace_report_syscall_entry (regs); +return ptrace_report_syscall_permit_entry (regs); }#endif
@@ -73,8 +74,6 @@ static inline void syscall_enter_audit(sstatic __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work,long syscall) { -long ret =0 ; -/* * Handle Syscall User Dispatch. This must comes first, since * the ABI here can be something that doesn't make sense for
@@ -95,8 +94,8 @@ static __always_inline long syscall_trac/* Handle ptrace */ if (work & (SYSCALL_WORK_SYSCALL_TRACE |SYSCALL_WORK_SYSCALL_EMU )) { - ret =arch_ptrace_report_syscall_entry (regs); -if (ret || (work &SYSCALL_WORK_SYSCALL_EMU )) +if (!arch_ptrace_report_syscall_permit_entry (regs) || + (work &SYSCALL_WORK_SYSCALL_EMU ))return -1L ; }
@@ -137,7 +136,7 @@ static __always_inline long syscall_trac* It handles the following work items: * * 1) syscall_work flag dependent invocations of -* ptrace_report_syscall_entry(), __seccomp_permit_syscall(), trace_sys_enter() +* ptrace_report_syscall_permit_entry(), __seccomp_permit_syscall(), trace_sys_enter() * 2) Invocation of audit_syscall_entry() */ static __always_inline long syscall_enter_from_user_mode_work (struct pt_regs *regs,long syscall)
include/linux/ptrace.h +6 -7
@@ -405,13 +405,13 @@ extern void sigaction_compat_abi(struct/* * ptrace report for syscall entry and exit looks identical. */ -static inline int ptrace_report_syscall (unsigned long message) +static inline bool ptrace_report_syscall (unsigned long message) {int ptrace = current->ptrace;int signr;if (!(ptrace &PT_PTRACED )) -return 0 ; +return true; signr =ptrace_notify (SIGTRAP | ((ptrace &PT_TRACESYSGOOD ) ?0x80 :0 ), message);
@@ -424,11 +424,11 @@ static inline int ptrace_report_syscall(if (signr)send_sig (signr, current,1 ); -return fatal_signal_pending (current); +return !fatal_signal_pending (current); }/** -* ptrace_report_syscall_entry - task is about to attempt a system call +* ptrace_report_syscall_permit_entry - task is about to attempt a system call * @regs: user register state of current task * * This will be called if %SYSCALL_WORK_SYSCALL_TRACE or
@@ -438,7 +438,7 @@ static inline int ptrace_report_syscall(* call number and arguments to be tried. It is safe to block here, * preventing the system call from beginning. * -* Returns zero normally, or nonzero if the calling arch code should abort +* Returns True normally, or False if the calling architecture code should abort * the system call. That must prevent normal entry so no system call is * made. If @task ever returns to user mode after this, its register state * is unspecified, but should be something harmless like an %ENOSYS error
@@ -447,8 +447,7 @@ static inline int ptrace_report_syscall(* * Called without locks, just after entering kernel mode. */ -static inline __must_check int ptrace_report_syscall_entry ( -struct pt_regs *regs) +static inline __must_check bool ptrace_report_syscall_permit_entry (struct pt_regs *regs) {return ptrace_report_syscall (PTRACE_EVENTMSG_SYSCALL_ENTRY ); }
Re: [patch 12/18] ptrace, treewide: Rename ptrace_report_syscall_entry() to ptrace_report_syscall_permit_entry()
Quoted 5 lines · Thomas Gleixner
The return value of that function is boolean and tells the caller whether to permit the syscall processing or not.
Rename the function so the purpose is clear and make the return type bool.
Just in case,
Re: [patch 12/18] ptrace, treewide: Rename ptrace_report_syscall_entry() to ptrace_report_syscall_permit_entry()
In reply to Thomas GleixnerQuoted 380 lines · Thomas Gleixner
The return value of that function is boolean and tells the caller whether to permit the syscall processing or not.
Rename the function so the purpose is clear and make the return type bool.
Signed-off-by Thomas Gleixner <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Oleg Nesterov <[email protected]>Cc Richard Henderson <[email protected]>Cc Vineet Gupta <[email protected]>Cc Russell King <[email protected]>Cc Catalin Marinas <[email protected]>Cc Will Deacon <[email protected]>Cc Guo Ren <[email protected]>Cc Brian Cain <[email protected]>Cc Geert Uytterhoeven <[email protected]>Cc Michal Simek <[email protected]>Cc Thomas Bogendoerfer <[email protected]>Cc Dinh Nguyen <[email protected]>Cc Helge Deller <[email protected]>Cc Yoshinori Sato <[email protected]>Cc "David S. Miller" <[email protected]>Cc Andreas Larsson <[email protected]>Cc Chris Zankel <[email protected]>--- arch/alpha/kernel/ptrace.c | 2 +- arch/arc/kernel/ptrace.c | 2 +- arch/arm/kernel/ptrace.c | 2 +- arch/arm64/kernel/ptrace.c | 2 +- arch/csky/kernel/ptrace.c | 2 +- arch/hexagon/kernel/traps.c | 2 +- arch/m68k/kernel/ptrace.c | 2 +- arch/microblaze/kernel/ptrace.c | 2 +- arch/mips/kernel/ptrace.c | 2 +- arch/nios2/kernel/ptrace.c | 2 +- arch/openrisc/kernel/ptrace.c | 2 +- arch/parisc/kernel/ptrace.c | 10 ++++------ arch/sh/kernel/ptrace_32.c | 2 +- arch/sparc/kernel/ptrace_32.c | 2 +- arch/sparc/kernel/ptrace_64.c | 2 +- arch/um/kernel/ptrace.c | 2 +- arch/xtensa/kernel/ptrace.c | 2 +- include/asm-generic/syscall.h | 4 ++-- include/linux/entry-common.h | 25 ++++++++++++------------- include/linux/ptrace.h | 13 ++++++------- 20 files changed, 40 insertions(+), 44 deletions(-)arch/alpha/kernel/ptrace.c +1
-1@@ -375,7 +375,7 @@ asmlinkage unsigned long syscall_trace_estruct pt_regs *regs =current_pt_regs ();if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) { + !ptrace_report_syscall_permit_entry (regs)) {syscall_set_nr (current, regs,-1 );if (regs->r19 ==0 && regs->r0 == (unsigned long )-1 )syscall_set_return_value (current, regs, -ENOSYS ,0 );arch/arc/kernel/ptrace.c +1
-1@@ -342,7 +342,7 @@ long arch_ptrace(struct task_struct *chi asmlinkage int syscall_trace_enter(struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE )) -if (ptrace_report_syscall_entry (regs)) +if (!ptrace_report_syscall_permit_entry (regs))return ULONG_MAX ;#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS arch/arm/kernel/ptrace.c +1
-1@@ -840,7 +840,7 @@ static void report_syscall(struct pt_regif (dir ==PTRACE_SYSCALL_EXIT )ptrace_report_syscall_exit (regs,0 ); -else if (ptrace_report_syscall_entry (regs)) +else if (!ptrace_report_syscall_permit_entry (regs))current_thread_info ()->abi_syscall =-1 ; regs->ARM_ip = ip;arch/arm64/kernel/ptrace.c +1
-1@@ -2379,7 +2379,7 @@ static int report_syscall_entry(struct pint regno, ret; saved_reg =ptrace_save_reg (regs,PTRACE_SYSCALL_ENTER , ®no); - ret =ptrace_report_syscall_entry (regs); + ret = !ptrace_report_syscall_permit_entry (regs);if (ret)forget_syscall (regs); regs->regs[regno] = saved_reg;arch/csky/kernel/ptrace.c +1
-1@@ -320,7 +320,7 @@ long arch_ptrace(struct task_struct *chi asmlinkage int syscall_trace_enter(struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE )) -if (ptrace_report_syscall_entry (regs)) +if (!ptrace_report_syscall_permit_entry (regs))return -1 ;if (!seccomp_permit_syscall ())arch/hexagon/kernel/traps.c +1
-1@@ -345,7 +345,7 @@ void do_trap0(struct pt_regs *regs)/* allow strace to catch syscall args */ if (unlikely (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs))) + !ptrace_report_syscall_permit_entry (regs)))return ;/* return -ENOSYS somewhere? */ /* Interrupts should be re-enabled for syscall processing */ arch/m68k/kernel/ptrace.c +1
-1@@ -279,7 +279,7 @@ asmlinkage int syscall_trace_enter(void)int ret =0 ;if (test_thread_flag (TIF_SYSCALL_TRACE )) - ret =ptrace_report_syscall_entry (task_pt_regs (current)); + ret = !ptrace_report_syscall_permit_entry (task_pt_regs (current));if (!seccomp_permit_syscall ())return -1 ;arch/microblaze/kernel/ptrace.c +1
-1@@ -139,7 +139,7 @@ asmlinkage unsigned long do_syscall_tracsecure_computing_strict (regs->r12);if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) + !ptrace_report_syscall_permit_entry (regs))/* * Tracing decided this syscall should not happen. * We'll return a bogus call number to get an ENOSYS arch/mips/kernel/ptrace.c +1
-1@@ -1324,7 +1324,7 @@ asmlinkage long syscall_trace_enter(struuser_exit ();if (test_thread_flag (TIF_SYSCALL_TRACE )) { -if (ptrace_report_syscall_entry (regs)) +if (!ptrace_report_syscall_permit_entry (regs))return -1 ; }arch/nios2/kernel/ptrace.c +1
-1@@ -133,7 +133,7 @@ asmlinkage int do_syscall_trace_enter(voint ret =0 ;if (test_thread_flag (TIF_SYSCALL_TRACE )) - ret =ptrace_report_syscall_entry (task_pt_regs (current)); + ret = !ptrace_report_syscall_permit_entry (task_pt_regs (current));return ret; }arch/openrisc/kernel/ptrace.c +1
-1@@ -293,7 +293,7 @@ asmlinkage long do_syscall_trace_enter(slong ret =0 ;if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) + !ptrace_report_syscall_permit_entry (regs))/* * Tracing decided this syscall should not happen. * We'll return a bogus call number to get an ENOSYS arch/parisc/kernel/ptrace.c +4
-6@@ -326,7 +326,7 @@ long compat_arch_ptrace(struct task_strulong do_syscall_trace_enter (struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE )) { -int rc =ptrace_report_syscall_entry (regs); +bool permit =ptrace_report_syscall_permit_entry (regs);/* * As tracesys_next does not set %r28 to -ENOSYS @@ -334,12 +334,10 @@ long do_syscall_trace_enter(struct pt_re*/ regs->gr[28 ] = -ENOSYS ; -if (rc) { +if (!permit) {/* -* A nonzero return code from -* ptrace_report_syscall_entry() tells us -* to prevent the syscall execution. Skip -* the syscall call and the syscall restart handling. +* Skip the syscall call and the syscall restart +* handling. * * Note that the tracer may also just change * regs->gr[20] to an invalid syscall number, arch/sh/kernel/ptrace_32.c +1
-1@@ -455,7 +455,7 @@ long arch_ptrace(struct task_struct *chiasmlinkage long do_syscall_trace_enter (struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) { + !ptrace_report_syscall_permit_entry (regs)) { regs->regs[0 ] = -ENOSYS ;return -1 ; }arch/sparc/kernel/ptrace_32.c +1
-1@@ -441,7 +441,7 @@ asmlinkage int syscall_trace(struct pt_rif (syscall_exit_p)ptrace_report_syscall_exit (regs,0 );else - ret =ptrace_report_syscall_entry (regs); + ret = !ptrace_report_syscall_permit_entry (regs); }return ret;arch/sparc/kernel/ptrace_64.c +1
-1@@ -1093,7 +1093,7 @@ asmlinkage int syscall_trace_enter(strucuser_exit ();if (test_thread_flag (TIF_SYSCALL_TRACE )) - ret =ptrace_report_syscall_entry (regs); + ret = !ptrace_report_syscall_permit_entry (regs);if (unlikely (test_thread_flag (TIF_SYSCALL_TRACEPOINT )))trace_sys_enter (regs, regs->u_regs[UREG_G1 ]);arch/um/kernel/ptrace.c +1
-1@@ -135,7 +135,7 @@ int syscall_trace_enter(struct pt_regs *if (!test_thread_flag (TIF_SYSCALL_TRACE ))return 0 ; -return ptrace_report_syscall_entry (regs); +return !ptrace_report_syscall_permit_entry (regs); }void syscall_trace_leave (struct pt_regs *regs)arch/xtensa/kernel/ptrace.c +1
-1@@ -547,7 +547,7 @@ int do_syscall_trace_enter(struct pt_reg regs->areg[2 ] = -ENOSYS ;if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) { + !ptrace_report_syscall_permit_entry (regs)) { regs->areg[2 ] = -ENOSYS ; regs->syscall =NO_SYSCALL ;return 0 ;include/asm-generic/syscall.h +2
-2@@ -58,8 +58,8 @@ void syscall_set_nr(struct task_struct ** * It's only valid to call this when @task is stopped for system * call exit tracing (due to %SYSCALL_WORK_SYSCALL_TRACE or -* %SYSCALL_WORK_SYSCALL_AUDIT), after ptrace_report_syscall_entry() -* returned nonzero to prevent the system call from taking place. +* %SYSCALL_WORK_SYSCALL_AUDIT), after ptrace_report_syscall_permit_entry() +* returned False to prevent the system call from taking place. * * This rolls back the register state in @regs so it's as if the * system call instruction was a no-op. The registers containing include/linux/entry-common.h +12
-13@@ -38,21 +38,22 @@ SYSCALL_WORK_SYSCALL_EXIT_TRAP)/** -* arch_ptrace_report_syscall_entry - Architecture specific ptrace_report_syscall_entry() wrapper +* arch_ptrace_report_syscall_permit_entry - Architecture specific wrapper for +* ptrace_report_syscall_permit_entry() * @regs: Pointer to the register state at syscall entry * -* Invoked from syscall_trace_enter() to wrap ptrace_report_syscall_entry(). +* Invoked from syscall_trace_enter() to wrap ptrace_report_syscall_permit_entry(). * -* This allows architecture specific ptrace_report_syscall_entry() +* This allows architecture specific ptrace_report_syscall_permit_entry() * implementations. If not defined by the architecture this falls back to -* to ptrace_report_syscall_entry(). +* to ptrace_report_syscall_permit_entry(). */ -static __always_inline int arch_ptrace_report_syscall_entry(struct pt_regs *regs); +static __always_inline bool arch_ptrace_report_syscall_permit_entry(struct pt_regs *regs); -#ifndef arch_ptrace_report_syscall_entry -static __always_inline int arch_ptrace_report_syscall_entry(struct pt_regs *regs) +#ifndef arch_ptrace_report_syscall_permit_entry +static __always_inline bool arch_ptrace_report_syscall_permit_entry(struct pt_regs *regs) { -return ptrace_report_syscall_entry (regs); +return ptrace_report_syscall_permit_entry (regs); }#endif @@ -73,8 +74,6 @@ static inline void syscall_enter_audit(sstatic __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work,long syscall) { -long ret =0 ; -/* * Handle Syscall User Dispatch. This must comes first, since * the ABI here can be something that doesn't make sense for @@ -95,8 +94,8 @@ static __always_inline long syscall_trac/* Handle ptrace */ if (work & (SYSCALL_WORK_SYSCALL_TRACE |SYSCALL_WORK_SYSCALL_EMU )) { - ret =arch_ptrace_report_syscall_entry (regs); -if (ret || (work &SYSCALL_WORK_SYSCALL_EMU )) +if (!arch_ptrace_report_syscall_permit_entry (regs) || + (work &SYSCALL_WORK_SYSCALL_EMU ))return -1L ; }@@ -137,7 +136,7 @@ static __always_inline long syscall_trac* It handles the following work items: * * 1) syscall_work flag dependent invocations of -* ptrace_report_syscall_entry(), __seccomp_permit_syscall(), trace_sys_enter() +* ptrace_report_syscall_permit_entry(), __seccomp_permit_syscall(), trace_sys_enter() * 2) Invocation of audit_syscall_entry() */ static __always_inline long syscall_enter_from_user_mode_work (struct pt_regs *regs,long syscall)include/linux/ptrace.h +5
-5@@ -405,13 +405,13 @@ extern void sigaction_compat_abi(struct/* * ptrace report for syscall entry and exit looks identical. */ -static inline int ptrace_report_syscall (unsigned long message) +static inline bool ptrace_report_syscall (unsigned long message) {int ptrace = current->ptrace;int signr;if (!(ptrace &PT_PTRACED )) -return 0 ; +return true; signr =ptrace_notify (SIGTRAP | ((ptrace &PT_TRACESYSGOOD ) ?0x80 :0 ), message);@@ -424,11 +424,11 @@ static inline int ptrace_report_syscall(if (signr)send_sig (signr, current,1 ); -return fatal_signal_pending (current); +return !fatal_signal_pending (current); }/** -* ptrace_report_syscall_entry - task is about to attempt a system call +* ptrace_report_syscall_permit_entry - task is about to attempt a system call * @regs: user register state of current task * * This will be called if %SYSCALL_WORK_SYSCALL_TRACE or @@ -438,7 +438,7 @@ static inline int ptrace_report_syscall(* call number and arguments to be tried. It is safe to block here, * preventing the system call from beginning. * -* Returns zero normally, or nonzero if the calling arch code should abort +* Returns True normally, or False if the calling architecture code should abort * the system call. That must prevent normal entry so no system call is * made. If @task ever returns to user mode after this, its register state * is unspecified, but should be something harmless like an %ENOSYS error
include/linux/ptrace.h static inline int ptrace_report_syscall( · line 453
Quoted 9 lines
include/linux/ptrace.h +1
-2@@ -447,8 +447,7 @@ static inline int ptrace_report_syscall(* * Called without locks, just after entering kernel mode. */ -static inline __must_check int ptrace_report_syscall_entry ( -struct pt_regs *regs) +static inline __must_check bool ptrace_report_syscall_permit_entry (struct pt_regs *regs) {return ptrace_report_syscall (PTRACE_EVENTMSG_SYSCALL_ENTRY ); }
Quoted 1 line
Re: [patch 12/18] ptrace, treewide: Rename ptrace_report_syscall_entry() to ptrace_report_syscall_permit_entry()
In reply to Thomas GleixnerQuoted 6 lines · Thomas Gleixner
The return value of that function is boolean and tells the caller whether to permit the syscall processing or not.
Rename the function so the purpose is clear and make the return type bool.
arch/m68k/kernel/ptrace.c | 2 +-
Gr{oetje,eeting}s,
Geert
Signature · 5 lines
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected] In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Re: [patch 12/18] ptrace, treewide: Rename ptrace_report_syscall_entry() to ptrace_report_syscall_permit_entry()
In reply to Thomas GleixnerQuoted 380 lines · Thomas Gleixner
The return value of that function is boolean and tells the caller whether to permit the syscall processing or not.
Rename the function so the purpose is clear and make the return type bool.
Signed-off-by Thomas Gleixner <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Oleg Nesterov <[email protected]>Cc Richard Henderson <[email protected]>Cc Vineet Gupta <[email protected]>Cc Russell King <[email protected]>Cc Catalin Marinas <[email protected]>Cc Will Deacon <[email protected]>Cc Guo Ren <[email protected]>Cc Brian Cain <[email protected]>Cc Geert Uytterhoeven <[email protected]>Cc Michal Simek <[email protected]>Cc Thomas Bogendoerfer <[email protected]>Cc Dinh Nguyen <[email protected]>Cc Helge Deller <[email protected]>Cc Yoshinori Sato <[email protected]>Cc "David S. Miller" <[email protected]>Cc Andreas Larsson <[email protected]>Cc Chris Zankel <[email protected]>---
arch/alpha/kernel/ptrace.c | 2 +- arch/arc/kernel/ptrace.c | 2 +- arch/arm/kernel/ptrace.c | 2 +- arch/arm64/kernel/ptrace.c | 2 +- arch/csky/kernel/ptrace.c | 2 +- arch/hexagon/kernel/traps.c | 2 +- arch/m68k/kernel/ptrace.c | 2 +-arch/microblaze/kernel/ptrace.c| 2 +- arch/mips/kernel/ptrace.c | 2 +- arch/nios2/kernel/ptrace.c | 2 +- arch/openrisc/kernel/ptrace.c | 2 +- arch/parisc/kernel/ptrace.c | 10 ++++------ arch/sh/kernel/ptrace_32.c | 2 +- arch/sparc/kernel/ptrace_32.c | 2 +- arch/sparc/kernel/ptrace_64.c | 2 +- arch/um/kernel/ptrace.c | 2 +- arch/xtensa/kernel/ptrace.c | 2 +- include/asm-generic/syscall.h | 4 ++-- include/linux/entry-common.h | 25 ++++++++++++------------- include/linux/ptrace.h | 13 ++++++-------20 files changed, 40 insertions(+), 44 deletions(-)arch/alpha/kernel/ptrace.c +0
-0@@ -375,7 +375,7 @@ asmlinkage unsigned long syscall_trace_e struct pt_regs *regs = current_pt_regs();
if (test_thread_flag(TIF_SYSCALL_TRACE)&&arch/alpha/kernel/ptrace.c +1
-1- ptrace_report_syscall_entry(regs)) { + !ptrace_report_syscall_permit_entry(regs)) {
syscall_set_nr(current, regs, -1);
if (regs->r19== 0 &®s->r0== (unsigned long)-1)syscall_set_return_value(current, regs, -ENOSYS, 0);arch/arc/kernel/ptrace.c +1
-1@@ -342,7 +342,7 @@ long arch_ptrace(struct task_struct *chi asmlinkage int syscall_trace_enter(struct pt_regs *regs) { if (test_thread_flag(TIF_SYSCALL_TRACE)) -if (ptrace_report_syscall_entry (regs)) +if (!ptrace_report_syscall_permit_entry (regs)) return ULONG_MAX;
#ifdefCONFIG_HAVE_SYSCALL_TRACEPOINTSarch/arm/kernel/ptrace.c +0
-0@@ -840,7 +840,7 @@ static void report_syscall(struct pt_reg
if (dir ==PTRACE_SYSCALL_EXIT)ptrace_report_syscall_exit(regs, 0);arch/arm/kernel/ptrace.c +1
-1-else if (ptrace_report_syscall_entry (regs)) +else if (!ptrace_report_syscall_permit_entry (regs))current_thread_info()->abi_syscall = -1;
regs->ARM_ip= ip;arch/arm64/kernel/ptrace.c +0
-0@@ -2379,7 +2379,7 @@ static int report_syscall_entry(struct p int regno, ret;
saved_reg=ptrace_save_reg(regs, PTRACE_SYSCALL_ENTER, ®no);arch/arm64/kernel/ptrace.c +1
-1- ret =ptrace_report_syscall_entry (regs); + ret = !ptrace_report_syscall_permit_entry (regs);if (ret)
forget_syscall(regs);
regs->regs[regno] =saved_reg;arch/csky/kernel/ptrace.c +1
-1@@ -320,7 +320,7 @@ long arch_ptrace(struct task_struct *chi asmlinkage int syscall_trace_enter(struct pt_regs *regs) { if (test_thread_flag(TIF_SYSCALL_TRACE)) -if (ptrace_report_syscall_entry (regs)) +if (!ptrace_report_syscall_permit_entry (regs)) return -1;
if (!seccomp_permit_syscall())arch/hexagon/kernel/traps.c +0
-0@@ -345,7 +345,7 @@ void do_trap0(struct pt_regs *regs)
/* allow strace to catch syscall args */ if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE) &&arch/hexagon/kernel/traps.c +1
-1- ptrace_report_syscall_entry(regs))) + !ptrace_report_syscall_permit_entry(regs)))return; /* return
-ENOSYSsomewhere? */
/* Interrupts should be re-enabled for syscall processing */arch/m68k/kernel/ptrace.c +0
-0@@ -279,7 +279,7 @@ asmlinkage int syscall_trace_enter(void) int ret = 0;
if (test_thread_flag(TIF_SYSCALL_TRACE))arch/m68k/kernel/ptrace.c +1
-1- ret =ptrace_report_syscall_entry (task_pt_regs (current)); + ret = !ptrace_report_syscall_permit_entry (task_pt_regs (current));
if (!seccomp_permit_syscall())
return -1;arch/microblaze/kernel/ptrace.c +0
-0@@ -139,7 +139,7 @@ asmlinkage unsigned long do_syscall_trac secure_computing_strict(regs->r12);
if (test_thread_flag(TIF_SYSCALL_TRACE)&&arch/microblaze/kernel/ptrace.c +1
-1- ptrace_report_syscall_entry(regs)) + !ptrace_report_syscall_permit_entry(regs))/*
* Tracing decided this syscall should not happen.
* We'll return a bogus call number to get an ENOSYSarch/mips/kernel/ptrace.c +0
-0@@ -1324,7 +1324,7 @@ asmlinkage long syscall_trace_enter(stru user_exit();
if (test_thread_flag(TIF_SYSCALL_TRACE)) {arch/mips/kernel/ptrace.c +1
-1-if (ptrace_report_syscall_entry (regs)) +if (!ptrace_report_syscall_permit_entry (regs))return -1;
}arch/nios2/kernel/ptrace.c +0
-0@@ -133,7 +133,7 @@ asmlinkage int do_syscall_trace_enter(vo int ret = 0;
if (test_thread_flag(TIF_SYSCALL_TRACE))arch/nios2/kernel/ptrace.c +1
-1- ret =ptrace_report_syscall_entry (task_pt_regs (current)); + ret = !ptrace_report_syscall_permit_entry (task_pt_regs (current));
return ret;
}arch/openrisc/kernel/ptrace.c +0
-0@@ -293,7 +293,7 @@ asmlinkage long do_syscall_trace_enter(s long ret = 0;
if (test_thread_flag(TIF_SYSCALL_TRACE)&&arch/openrisc/kernel/ptrace.c +1
-1- ptrace_report_syscall_entry(regs)) + !ptrace_report_syscall_permit_entry(regs))/*
* Tracing decided this syscall should not happen.
* We'll return a bogus call number to get an ENOSYSarch/parisc/kernel/ptrace.c +1
-1@@ -326,7 +326,7 @@ long compat_arch_ptrace(struct task_stru long do_syscall_trace_enter(struct pt_regs *regs) { if (test_thread_flag(TIF_SYSCALL_TRACE)) { -int rc =ptrace_report_syscall_entry (regs); +bool permit =ptrace_report_syscall_permit_entry (regs);
/*
* Astracesys_nextdoes not set %r28 to-ENOSYSarch/parisc/kernel/ptrace.c +0
-0@@ -334,12 +334,10 @@ long do_syscall_trace_enter(struct pt_re*/ regs->gr[28] = -ENOSYS;arch/parisc/kernel/ptrace.c +1
-1-if (rc) { +if (!permit) {/*
arch/parisc/kernel/ptrace.c +2
-4-* A nonzero return code from -* ptrace_report_syscall_entry() tells us -* to prevent the syscall execution. Skip -* the syscall call and the syscall restart handling. +* Skip the syscall call and the syscall restart +* handling. *
* Note that the tracer may also just change
* regs->gr[20] to an invalid syscall number,arch/sh/kernel/ptrace_32.c +0
-0@@ -455,7 +455,7 @@ long arch_ptrace(struct task_struct *chi asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) {if (
test_thread_flag(TIF_SYSCALL_TRACE)&&arch/sh/kernel/ptrace_32.c +1
-1- ptrace_report_syscall_entry(regs)) { + !ptrace_report_syscall_permit_entry(regs)) {regs->regs[0] =
-ENOSYS;
return -1;
}arch/sparc/kernel/ptrace_32.c +0
-0@@ -441,7 +441,7 @@ asmlinkage int syscall_trace(struct pt_r if (syscall_exit_p) ptrace_report_syscall_exit(regs, 0);else
arch/sparc/kernel/ptrace_32.c +1
-1- ret =ptrace_report_syscall_entry (regs); + ret = !ptrace_report_syscall_permit_entry (regs);}
return ret;arch/sparc/kernel/ptrace_64.c +0
-0@@ -1093,7 +1093,7 @@ asmlinkage int syscall_trace_enter(struc user_exit();
if (test_thread_flag(TIF_SYSCALL_TRACE))arch/sparc/kernel/ptrace_64.c +1
-1- ret =ptrace_report_syscall_entry (regs); + ret = !ptrace_report_syscall_permit_entry (regs);
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))trace_sys_enter(regs, regs->u_regs[UREG_G1]);arch/um/kernel/ptrace.c +0
-0@@ -135,7 +135,7 @@ int syscall_trace_enter(struct pt_regs * if (!test_thread_flag(TIF_SYSCALL_TRACE)) return 0;arch/um/kernel/ptrace.c +1
-1-return ptrace_report_syscall_entry (regs); +return !ptrace_report_syscall_permit_entry (regs);}
voidsyscall_trace_leave(struct pt_regs *regs)arch/xtensa/kernel/ptrace.c +0
-0@@ -547,7 +547,7 @@ int do_syscall_trace_enter(struct pt_reg regs->areg[2] = -ENOSYS;
if (test_thread_flag(TIF_SYSCALL_TRACE)&&arch/xtensa/kernel/ptrace.c +1
-1- ptrace_report_syscall_entry(regs)) { + !ptrace_report_syscall_permit_entry(regs)) {regs->areg[2] =
-ENOSYS;
regs->syscall=NO_SYSCALL;
return 0;include/asm-generic/syscall.h +2
-2@@ -58,8 +58,8 @@ void syscall_set_nr(struct task_struct * * * It's only valid to call this when @task is stopped for system * call exit tracing (due to %SYSCALL_WORK_SYSCALL_TRACE or - * %SYSCALL_WORK_SYSCALL_AUDIT), after ptrace_report_syscall_entry() - * returned nonzero to prevent the system call from taking place. + * %SYSCALL_WORK_SYSCALL_AUDIT), after ptrace_report_syscall_permit_entry() + * returned False to prevent the system call from taking place. * * This rolls back the register state in @regs so it's as if the * system call instruction was a no-op. The registers containinginclude/linux/entry-common.h +0
-0@@ -38,21 +38,22 @@ SYSCALL_WORK_SYSCALL_EXIT_TRAP)
/**
- *arch_ptrace_report_syscall_entry- Architecture specificptrace_report_syscall_entry()wrapper
+ *arch_ptrace_report_syscall_permit_entry- Architecture specific wrapper for
+ *ptrace_report_syscall_permit_entry()
* @regs: Pointer to the register state at syscall entry
*
- * Invoked fromsyscall_trace_enter()to wrapptrace_report_syscall_entry().
+ * Invoked fromsyscall_trace_enter()to wrapptrace_report_syscall_permit_entry(). *
- * This allows architecture specificptrace_report_syscall_entry()
+ * This allows architecture specificptrace_report_syscall_permit_entry()
* implementations. If not defined by the architecture this falls back to
- * toptrace_report_syscall_entry().
+ * toptrace_report_syscall_permit_entry().
*/include/linux/entry-common.h +1
-1-static __always_inline int arch_ptrace_report_syscall_entry(struct pt_regs *regs); +static __always_inline bool arch_ptrace_report_syscall_permit_entry(struct pt_regs *regs);include/linux/entry-common.h +2
-2-#ifndef arch_ptrace_report_syscall_entry -static __always_inline int arch_ptrace_report_syscall_entry(struct pt_regs *regs) +#ifndef arch_ptrace_report_syscall_permit_entry +static __always_inline bool arch_ptrace_report_syscall_permit_entry(struct pt_regs *regs){
include/linux/entry-common.h +1
-1-return ptrace_report_syscall_entry (regs); +return ptrace_report_syscall_permit_entry (regs);}
#endifinclude/linux/entry-common.h +0
-2@@ -73,8 +74,6 @@ static inline void syscall_enter_audit(s static __always_inline long syscall_trace_enter(struct pt_regs *regs, unsigned long work, long syscall) { -long ret =0 ; - /** Handle Syscall User Dispatch. This must comes first, since * the ABI here can be something that doesn't make sense for @@ -95,8 +94,8 @@ static __always_inline long syscall_trac
/* Handle ptrace */
if (work & (SYSCALL_WORK_SYSCALL_TRACE|SYSCALL_WORK_SYSCALL_EMU)) {include/linux/entry-common.h +2
-2- ret =arch_ptrace_report_syscall_entry (regs); -if (ret || (work &SYSCALL_WORK_SYSCALL_EMU )) +if (!arch_ptrace_report_syscall_permit_entry (regs) || + (work & SYSCALL_WORK_SYSCALL_EMU))return -1L;
}include/linux/entry-common.h +1
-1@@ -137,7 +136,7 @@ static __always_inline long syscall_trac* It handles the following work items: * * 1) syscall_work flag dependent invocations of -* ptrace_report_syscall_entry(), __seccomp_permit_syscall(), trace_sys_enter() +* ptrace_report_syscall_permit_entry(), __seccomp_permit_syscall(), trace_sys_enter() * 2) Invocation of audit_syscall_entry() */ static __always_inline long syscall_enter_from_user_mode_work(struct pt_regs *regs, long syscall)include/linux/ptrace.h +1
-1@@ -405,13 +405,13 @@ extern void sigaction_compat_abi(struct /** ptrace report for syscall entry and exit looks identical. */ -static inline int ptrace_report_syscall (unsigned long message) +static inline bool ptrace_report_syscall (unsigned long message) { int ptrace = current->ptrace; int signr;
if (!(ptrace &PT_PTRACED))include/linux/ptrace.h +1
-1-return 0 ; +return true;
signr =ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0), message);include/linux/ptrace.h +0
-0@@ -424,11 +424,11 @@ static inline int ptrace_report_syscall( if (signr) send_sig(signr, current, 1);include/linux/ptrace.h +1
-1-return fatal_signal_pending (current); +return !fatal_signal_pending (current);}
/**
- *ptrace_report_syscall_entry- task is about to attempt a system call
+ *ptrace_report_syscall_permit_entry- task is about to attempt a system call
* @regs: user register state of current task
*
* This will be called if %SYSCALL_WORK_SYSCALL_TRACE orinclude/linux/ptrace.h +1
-1@@ -438,7 +438,7 @@ static inline int ptrace_report_syscall( * call number and arguments to be tried. It is safe to block here, * preventing the system call from beginning. * - * Returns zero normally, or nonzero if the calling arch code should abort + * Returns True normally, or False if the calling architecture code should abort * the system call. That must prevent normal entry so no system call is * made. If @task ever returns to user mode after this, its register state * is unspecified, but should be something harmless like an %ENOSYS error
include/linux/ptrace.h static inline int ptrace_report_syscall( · line 453
Quoted 9 lines
include/linux/ptrace.h +1
-2@@ -447,8 +447,7 @@ static inline int ptrace_report_syscall(* * Called without locks, just after entering kernel mode. */ -static inline __must_check int ptrace_report_syscall_entry ( -struct pt_regs *regs) +static inline __must_check bool ptrace_report_syscall_permit_entry (struct pt_regs *regs) { return ptrace_report_syscall(PTRACE_EVENTMSG_SYSCALL_ENTRY); }
Re: [patch 12/18] ptrace, treewide: Rename ptrace_report_syscall_entry() to ptrace_report_syscall_permit_entry()
In reply to Thomas GleixnerQuoted 60 lines · Thomas Gleixner
The return value of that function is boolean and tells the caller whether to permit the syscall processing or not.
Rename the function so the purpose is clear and make the return type bool.
Signed-off-by Thomas Gleixner <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Oleg Nesterov <[email protected]>Cc Richard Henderson <[email protected]>Cc Vineet Gupta <[email protected]>Cc Russell King <[email protected]>Cc Catalin Marinas <[email protected]>Cc Will Deacon <[email protected]>Cc Guo Ren <[email protected]>Cc Brian Cain <[email protected]>Cc Geert Uytterhoeven <[email protected]>Cc Michal Simek <[email protected]>Cc Thomas Bogendoerfer <[email protected]>Cc Dinh Nguyen <[email protected]>Cc Helge Deller <[email protected]>Cc Yoshinori Sato <[email protected]>Cc "David S. Miller" <[email protected]>Cc Andreas Larsson <[email protected]>Cc Chris Zankel <[email protected]>--- arch/alpha/kernel/ptrace.c | 2 +- arch/arc/kernel/ptrace.c | 2 +- arch/arm/kernel/ptrace.c | 2 +- arch/arm64/kernel/ptrace.c | 2 +- arch/csky/kernel/ptrace.c | 2 +- arch/hexagon/kernel/traps.c | 2 +- arch/m68k/kernel/ptrace.c | 2 +- arch/microblaze/kernel/ptrace.c | 2 +- arch/mips/kernel/ptrace.c | 2 +- arch/nios2/kernel/ptrace.c | 2 +- arch/openrisc/kernel/ptrace.c | 2 +- arch/parisc/kernel/ptrace.c | 10 ++++------ arch/sh/kernel/ptrace_32.c | 2 +- arch/sparc/kernel/ptrace_32.c | 2 +- arch/sparc/kernel/ptrace_64.c | 2 +- arch/um/kernel/ptrace.c | 2 +- arch/xtensa/kernel/ptrace.c | 2 +- include/asm-generic/syscall.h | 4 ++-- include/linux/entry-common.h | 25 ++++++++++++------------- include/linux/ptrace.h | 13 ++++++------- 20 files changed, 40 insertions(+), 44 deletions(-)
[...]
Quoted 14 lines
arch/parisc/kernel/ptrace.c +1
-1@@ -326,7 +326,7 @@ long compat_arch_ptrace(struct task_strulong do_syscall_trace_enter (struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE )) { -int rc =ptrace_report_syscall_entry (regs); +bool permit =ptrace_report_syscall_permit_entry (regs);/* * As tracesys_next does not set %r28 to -ENOSYS @@ -334,12 +334,10 @@ long do_syscall_trace_enter(struct pt_re*/ regs->gr[28 ] = -ENOSYS ;
arch/parisc/kernel/ptrace.c long do_syscall_trace_enter(struct pt_re · line 340
Quoted 10 lines
arch/parisc/kernel/ptrace.c +3
-5-if (rc) { +if (!permit) {/* -* A nonzero return code from -* ptrace_report_syscall_entry() tells us -* to prevent the syscall execution. Skip -* the syscall call and the syscall restart handling. +* Skip the syscall call and the syscall restart +* handling.
Hey Thomas,
This comment syscall call sounds a bit weird.
Apart from this, Everything looks good.
Regards,
Mukesh
Re: [patch 12/18] ptrace, treewide: Rename ptrace_report_syscall_entry() to ptrace_report_syscall_permit_entry()
In reply to Thomas GleixnerHello,
why is the syscall -1 special-cased here?
Wouldn't any invalid syscall number such as -2 work equally well, making this whole 'permit' pinned on the -1 value bogus?
Quoted 63 lines · Thomas Gleixner
The return value of that function is boolean and tells the caller whether to permit the syscall processing or not.
Rename the function so the purpose is clear and make the return type bool.
Signed-off-by Thomas Gleixner <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Oleg Nesterov <[email protected]>Cc Richard Henderson <[email protected]>Cc Vineet Gupta <[email protected]>Cc Russell King <[email protected]>Cc Catalin Marinas <[email protected]>Cc Will Deacon <[email protected]>Cc Guo Ren <[email protected]>Cc Brian Cain <[email protected]>Cc Geert Uytterhoeven <[email protected]>Cc Michal Simek <[email protected]>Cc Thomas Bogendoerfer <[email protected]>Cc Dinh Nguyen <[email protected]>Cc Helge Deller <[email protected]>Cc Yoshinori Sato <[email protected]>Cc "David S. Miller" <[email protected]>Cc Andreas Larsson <[email protected]>Cc Chris Zankel <[email protected]>--- arch/alpha/kernel/ptrace.c | 2 +- arch/arc/kernel/ptrace.c | 2 +- arch/arm/kernel/ptrace.c | 2 +- arch/arm64/kernel/ptrace.c | 2 +- arch/csky/kernel/ptrace.c | 2 +- arch/hexagon/kernel/traps.c | 2 +- arch/m68k/kernel/ptrace.c | 2 +- arch/microblaze/kernel/ptrace.c | 2 +- arch/mips/kernel/ptrace.c | 2 +- arch/nios2/kernel/ptrace.c | 2 +- arch/openrisc/kernel/ptrace.c | 2 +- arch/parisc/kernel/ptrace.c | 10 ++++------ arch/sh/kernel/ptrace_32.c | 2 +- arch/sparc/kernel/ptrace_32.c | 2 +- arch/sparc/kernel/ptrace_64.c | 2 +- arch/um/kernel/ptrace.c | 2 +- arch/xtensa/kernel/ptrace.c | 2 +- include/asm-generic/syscall.h | 4 ++-- include/linux/entry-common.h | 25 ++++++++++++------------- include/linux/ptrace.h | 13 ++++++------- 20 files changed, 40 insertions(+), 44 deletions(-)
arch/alpha/kernel/ptrace.c asmlinkage unsigned long syscall_trace_e · line 379
Quoted 6 lines
arch/alpha/kernel/ptrace.c +1
-1@@ -375,7 +375,7 @@ asmlinkage unsigned long syscall_trace_estruct pt_regs *regs =current_pt_regs ();if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) { + !ptrace_report_syscall_permit_entry (regs)) {syscall_set_nr (current, regs,-1 );
Why is this done here?
Presumably the ptrace_report_syscall_entry returns false here becasue the tracer put -1 into whatever register specifies the syscall number (or it was there to start with) which was then read back, compared to -1, leading to returning false. Now it's set to -1 again?
Thanks
Michal
Quoted 321 lines
arch/alpha/kernel/ptrace.c +0
-0if (regs->r19 ==0 && regs->r0 == (unsigned long )-1 )syscall_set_return_value (current, regs, -ENOSYS ,0 );arch/arc/kernel/ptrace.c +1
-1@@ -342,7 +342,7 @@ long arch_ptrace(struct task_struct *chi asmlinkage int syscall_trace_enter(struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE )) -if (ptrace_report_syscall_entry (regs)) +if (!ptrace_report_syscall_permit_entry (regs))return ULONG_MAX ;#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS arch/arm/kernel/ptrace.c +1
-1@@ -840,7 +840,7 @@ static void report_syscall(struct pt_regif (dir ==PTRACE_SYSCALL_EXIT )ptrace_report_syscall_exit (regs,0 ); -else if (ptrace_report_syscall_entry (regs)) +else if (!ptrace_report_syscall_permit_entry (regs))current_thread_info ()->abi_syscall =-1 ; regs->ARM_ip = ip;arch/arm64/kernel/ptrace.c +1
-1@@ -2379,7 +2379,7 @@ static int report_syscall_entry(struct pint regno, ret; saved_reg =ptrace_save_reg (regs,PTRACE_SYSCALL_ENTER , ®no); - ret =ptrace_report_syscall_entry (regs); + ret = !ptrace_report_syscall_permit_entry (regs);if (ret)forget_syscall (regs); regs->regs[regno] = saved_reg;arch/csky/kernel/ptrace.c +1
-1@@ -320,7 +320,7 @@ long arch_ptrace(struct task_struct *chi asmlinkage int syscall_trace_enter(struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE )) -if (ptrace_report_syscall_entry (regs)) +if (!ptrace_report_syscall_permit_entry (regs))return -1 ;if (!seccomp_permit_syscall ())arch/hexagon/kernel/traps.c +1
-1@@ -345,7 +345,7 @@ void do_trap0(struct pt_regs *regs)/* allow strace to catch syscall args */ if (unlikely (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs))) + !ptrace_report_syscall_permit_entry (regs)))return ;/* return -ENOSYS somewhere? */ /* Interrupts should be re-enabled for syscall processing */ arch/m68k/kernel/ptrace.c +1
-1@@ -279,7 +279,7 @@ asmlinkage int syscall_trace_enter(void)int ret =0 ;if (test_thread_flag (TIF_SYSCALL_TRACE )) - ret =ptrace_report_syscall_entry (task_pt_regs (current)); + ret = !ptrace_report_syscall_permit_entry (task_pt_regs (current));if (!seccomp_permit_syscall ())return -1 ;arch/microblaze/kernel/ptrace.c +1
-1@@ -139,7 +139,7 @@ asmlinkage unsigned long do_syscall_tracsecure_computing_strict (regs->r12);if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) + !ptrace_report_syscall_permit_entry (regs))/* * Tracing decided this syscall should not happen. * We'll return a bogus call number to get an ENOSYS arch/mips/kernel/ptrace.c +1
-1@@ -1324,7 +1324,7 @@ asmlinkage long syscall_trace_enter(struuser_exit ();if (test_thread_flag (TIF_SYSCALL_TRACE )) { -if (ptrace_report_syscall_entry (regs)) +if (!ptrace_report_syscall_permit_entry (regs))return -1 ; }arch/nios2/kernel/ptrace.c +1
-1@@ -133,7 +133,7 @@ asmlinkage int do_syscall_trace_enter(voint ret =0 ;if (test_thread_flag (TIF_SYSCALL_TRACE )) - ret =ptrace_report_syscall_entry (task_pt_regs (current)); + ret = !ptrace_report_syscall_permit_entry (task_pt_regs (current));return ret; }arch/openrisc/kernel/ptrace.c +1
-1@@ -293,7 +293,7 @@ asmlinkage long do_syscall_trace_enter(slong ret =0 ;if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) + !ptrace_report_syscall_permit_entry (regs))/* * Tracing decided this syscall should not happen. * We'll return a bogus call number to get an ENOSYS arch/parisc/kernel/ptrace.c +4
-6@@ -326,7 +326,7 @@ long compat_arch_ptrace(struct task_strulong do_syscall_trace_enter (struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE )) { -int rc =ptrace_report_syscall_entry (regs); +bool permit =ptrace_report_syscall_permit_entry (regs);/* * As tracesys_next does not set %r28 to -ENOSYS @@ -334,12 +334,10 @@ long do_syscall_trace_enter(struct pt_re*/ regs->gr[28 ] = -ENOSYS ; -if (rc) { +if (!permit) {/* -* A nonzero return code from -* ptrace_report_syscall_entry() tells us -* to prevent the syscall execution. Skip -* the syscall call and the syscall restart handling. +* Skip the syscall call and the syscall restart +* handling. * * Note that the tracer may also just change * regs->gr[20] to an invalid syscall number, arch/sh/kernel/ptrace_32.c +1
-1@@ -455,7 +455,7 @@ long arch_ptrace(struct task_struct *chiasmlinkage long do_syscall_trace_enter (struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) { + !ptrace_report_syscall_permit_entry (regs)) { regs->regs[0 ] = -ENOSYS ;return -1 ; }arch/sparc/kernel/ptrace_32.c +1
-1@@ -441,7 +441,7 @@ asmlinkage int syscall_trace(struct pt_rif (syscall_exit_p)ptrace_report_syscall_exit (regs,0 );else - ret =ptrace_report_syscall_entry (regs); + ret = !ptrace_report_syscall_permit_entry (regs); }return ret;arch/sparc/kernel/ptrace_64.c +1
-1@@ -1093,7 +1093,7 @@ asmlinkage int syscall_trace_enter(strucuser_exit ();if (test_thread_flag (TIF_SYSCALL_TRACE )) - ret =ptrace_report_syscall_entry (regs); + ret = !ptrace_report_syscall_permit_entry (regs);if (unlikely (test_thread_flag (TIF_SYSCALL_TRACEPOINT )))trace_sys_enter (regs, regs->u_regs[UREG_G1 ]);arch/um/kernel/ptrace.c +1
-1@@ -135,7 +135,7 @@ int syscall_trace_enter(struct pt_regs *if (!test_thread_flag (TIF_SYSCALL_TRACE ))return 0 ; -return ptrace_report_syscall_entry (regs); +return !ptrace_report_syscall_permit_entry (regs); }void syscall_trace_leave (struct pt_regs *regs)arch/xtensa/kernel/ptrace.c +1
-1@@ -547,7 +547,7 @@ int do_syscall_trace_enter(struct pt_reg regs->areg[2 ] = -ENOSYS ;if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) { + !ptrace_report_syscall_permit_entry (regs)) { regs->areg[2 ] = -ENOSYS ; regs->syscall =NO_SYSCALL ;return 0 ;include/asm-generic/syscall.h +2
-2@@ -58,8 +58,8 @@ void syscall_set_nr(struct task_struct ** * It's only valid to call this when @task is stopped for system * call exit tracing (due to %SYSCALL_WORK_SYSCALL_TRACE or -* %SYSCALL_WORK_SYSCALL_AUDIT), after ptrace_report_syscall_entry() -* returned nonzero to prevent the system call from taking place. +* %SYSCALL_WORK_SYSCALL_AUDIT), after ptrace_report_syscall_permit_entry() +* returned False to prevent the system call from taking place. * * This rolls back the register state in @regs so it's as if the * system call instruction was a no-op. The registers containing include/linux/entry-common.h +12
-13@@ -38,21 +38,22 @@ SYSCALL_WORK_SYSCALL_EXIT_TRAP)/** -* arch_ptrace_report_syscall_entry - Architecture specific ptrace_report_syscall_entry() wrapper +* arch_ptrace_report_syscall_permit_entry - Architecture specific wrapper for +* ptrace_report_syscall_permit_entry() * @regs: Pointer to the register state at syscall entry * -* Invoked from syscall_trace_enter() to wrap ptrace_report_syscall_entry(). +* Invoked from syscall_trace_enter() to wrap ptrace_report_syscall_permit_entry(). * -* This allows architecture specific ptrace_report_syscall_entry() +* This allows architecture specific ptrace_report_syscall_permit_entry() * implementations. If not defined by the architecture this falls back to -* to ptrace_report_syscall_entry(). +* to ptrace_report_syscall_permit_entry(). */ -static __always_inline int arch_ptrace_report_syscall_entry(struct pt_regs *regs); +static __always_inline bool arch_ptrace_report_syscall_permit_entry(struct pt_regs *regs); -#ifndef arch_ptrace_report_syscall_entry -static __always_inline int arch_ptrace_report_syscall_entry(struct pt_regs *regs) +#ifndef arch_ptrace_report_syscall_permit_entry +static __always_inline bool arch_ptrace_report_syscall_permit_entry(struct pt_regs *regs) { -return ptrace_report_syscall_entry (regs); +return ptrace_report_syscall_permit_entry (regs); }#endif @@ -73,8 +74,6 @@ static inline void syscall_enter_audit(sstatic __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work,long syscall) { -long ret =0 ; -/* * Handle Syscall User Dispatch. This must comes first, since * the ABI here can be something that doesn't make sense for @@ -95,8 +94,8 @@ static __always_inline long syscall_trac/* Handle ptrace */ if (work & (SYSCALL_WORK_SYSCALL_TRACE |SYSCALL_WORK_SYSCALL_EMU )) { - ret =arch_ptrace_report_syscall_entry (regs); -if (ret || (work &SYSCALL_WORK_SYSCALL_EMU )) +if (!arch_ptrace_report_syscall_permit_entry (regs) || + (work &SYSCALL_WORK_SYSCALL_EMU ))return -1L ; }@@ -137,7 +136,7 @@ static __always_inline long syscall_trac* It handles the following work items: * * 1) syscall_work flag dependent invocations of -* ptrace_report_syscall_entry(), __seccomp_permit_syscall(), trace_sys_enter() +* ptrace_report_syscall_permit_entry(), __seccomp_permit_syscall(), trace_sys_enter() * 2) Invocation of audit_syscall_entry() */ static __always_inline long syscall_enter_from_user_mode_work (struct pt_regs *regs,long syscall)include/linux/ptrace.h +6
-7@@ -405,13 +405,13 @@ extern void sigaction_compat_abi(struct/* * ptrace report for syscall entry and exit looks identical. */ -static inline int ptrace_report_syscall (unsigned long message) +static inline bool ptrace_report_syscall (unsigned long message) {int ptrace = current->ptrace;int signr;if (!(ptrace &PT_PTRACED )) -return 0 ; +return true; signr =ptrace_notify (SIGTRAP | ((ptrace &PT_TRACESYSGOOD ) ?0x80 :0 ), message);@@ -424,11 +424,11 @@ static inline int ptrace_report_syscall(if (signr)send_sig (signr, current,1 ); -return fatal_signal_pending (current); +return !fatal_signal_pending (current); }/** -* ptrace_report_syscall_entry - task is about to attempt a system call +* ptrace_report_syscall_permit_entry - task is about to attempt a system call * @regs: user register state of current task * * This will be called if %SYSCALL_WORK_SYSCALL_TRACE or @@ -438,7 +438,7 @@ static inline int ptrace_report_syscall(* call number and arguments to be tried. It is safe to block here, * preventing the system call from beginning. * -* Returns zero normally, or nonzero if the calling arch code should abort +* Returns True normally, or False if the calling architecture code should abort * the system call. That must prevent normal entry so no system call is * made. If @task ever returns to user mode after this, its register state * is unspecified, but should be something harmless like an %ENOSYS error @@ -447,8 +447,7 @@ static inline int ptrace_report_syscall(* * Called without locks, just after entering kernel mode. */ -static inline __must_check int ptrace_report_syscall_entry ( -struct pt_regs *regs) +static inline __must_check bool ptrace_report_syscall_permit_entry (struct pt_regs *regs) {return ptrace_report_syscall (PTRACE_EVENTMSG_SYSCALL_ENTRY ); }
Oleg Nesterov
maintainerRe: [patch 12/18] ptrace, treewide: Rename ptrace_report_syscall_entry() to ptrace_report_syscall_permit_entry()
Quoted 13 lines · Michal Suchánek
arch/alpha/kernel/ptrace.c asmlinkage unsigned long syscall_trace_e · line 379
Quoted 10 lines
arch/alpha/kernel/ptrace.c +1
-1@@ -375,7 +375,7 @@ asmlinkage unsigned long syscall_trace_estruct pt_regs *regs =current_pt_regs ();if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) { + !ptrace_report_syscall_permit_entry (regs)) {syscall_set_nr (current, regs,-1 );Why is this done here?
Quoted 4 lines
Presumably the
ptrace_report_syscall_entryreturns false here becasue the tracer put -1 into whatever register specifies the syscall number (or it was there to start with) which was then read back, compared to -1, leading to returning false. Now it's set to -1 again?
I don't know why arch/alpha/ does syscall_set_nr(-1).
But note that ptrace_report_syscall_entry() doesn't even check whether the syscall number was changed. It only checks fatal_signal_pending().
Oleg.
[tip: core/entry] ptrace, treewide: Rename ptrace_report_syscall_entry() to ptrace_report_syscall_permit_entry()
In reply to Thomas GleixnerThe following commit has been merged into the core/entry branch of tip:
The following commit has been merged into the core/entry branch of tip:
Commit-ID: 622f04e97415e62bd2ab61f7a27e7a296e8467b7 Gitweb: https://git.kernel.org/tip/622f04e97415e62bd2ab61f7a27e7a296e8467b7 Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 07 Jul 2026 21:06:44 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Sun, 12 Jul 2026 12:38:02 +02:00
ptrace, treewide: Rename ptrace_report_syscall_entry() to ptrace_report_syscall_permit_entry()
The return value of that function is boolean and tells the caller whether to permit the syscall processing or not.
Rename the function so the purpose is clear and make the return type bool.
--- arch/alpha/kernel/ptrace.c | 2 +- arch/arc/kernel/ptrace.c | 2 +- arch/arm/kernel/ptrace.c | 2 +- arch/arm64/kernel/ptrace.c | 2 +- arch/csky/kernel/ptrace.c | 2 +- arch/hexagon/kernel/traps.c | 2 +- arch/m68k/kernel/ptrace.c | 2 +- arch/microblaze/kernel/ptrace.c | 2 +- arch/mips/kernel/ptrace.c | 2 +- arch/nios2/kernel/ptrace.c | 2 +- arch/openrisc/kernel/ptrace.c | 2 +- arch/parisc/kernel/ptrace.c | 10 ++++------ arch/sh/kernel/ptrace_32.c | 2 +- arch/sparc/kernel/ptrace_32.c | 2 +- arch/sparc/kernel/ptrace_64.c | 2 +- arch/um/kernel/ptrace.c | 2 +- arch/xtensa/kernel/ptrace.c | 2 +- include/asm-generic/syscall.h | 4 ++-- include/linux/entry-common.h | 25 ++++++++++++------------- include/linux/ptrace.h | 13 ++++++------- 20 files changed, 40 insertions(+), 44 deletions(-)
arch/alpha/kernel/ptrace.c +1 -1
@@ -375,7 +375,7 @@ asmlinkage unsigned long syscall_trace_enter(void)struct pt_regs *regs =current_pt_regs ();if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) { + !ptrace_report_syscall_permit_entry (regs)) {syscall_set_nr (current, regs,-1 );if (regs->r19 ==0 && regs->r0 == (unsigned long )-1 )syscall_set_return_value (current, regs, -ENOSYS ,0 );
arch/arc/kernel/ptrace.c +1 -1
@@ -342,7 +342,7 @@ long arch_ptrace(struct task_struct *child, long request, asmlinkage int syscall_trace_enter(struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE )) -if (ptrace_report_syscall_entry (regs)) +if (!ptrace_report_syscall_permit_entry (regs))return ULONG_MAX ;#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
arch/arm/kernel/ptrace.c +1 -1
@@ -840,7 +840,7 @@ static void report_syscall(struct pt_regs *regs, enum ptrace_syscall_dir dir)if (dir ==PTRACE_SYSCALL_EXIT )ptrace_report_syscall_exit (regs,0 ); -else if (ptrace_report_syscall_entry (regs)) +else if (!ptrace_report_syscall_permit_entry (regs))current_thread_info ()->abi_syscall =-1 ; regs->ARM_ip = ip;
arch/arm64/kernel/ptrace.c +1 -1
@@ -2379,7 +2379,7 @@ static int report_syscall_entry(struct pt_regs *regs)int regno, ret; saved_reg =ptrace_save_reg (regs,PTRACE_SYSCALL_ENTER , ®no); - ret =ptrace_report_syscall_entry (regs); + ret = !ptrace_report_syscall_permit_entry (regs);if (ret)forget_syscall (regs); regs->regs[regno] = saved_reg;
arch/csky/kernel/ptrace.c +1 -1
@@ -320,7 +320,7 @@ long arch_ptrace(struct task_struct *child, long request, asmlinkage int syscall_trace_enter(struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE )) -if (ptrace_report_syscall_entry (regs)) +if (!ptrace_report_syscall_permit_entry (regs))return -1 ;if (!seccomp_permit_syscall ())
arch/hexagon/kernel/traps.c +1 -1
@@ -345,7 +345,7 @@ void do_trap0(struct pt_regs *regs)/* allow strace to catch syscall args */ if (unlikely (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs))) + !ptrace_report_syscall_permit_entry (regs)))return ;/* return -ENOSYS somewhere? */ /* Interrupts should be re-enabled for syscall processing */
arch/m68k/kernel/ptrace.c +1 -1
@@ -279,7 +279,7 @@ asmlinkage int syscall_trace_enter(void)int ret =0 ;if (test_thread_flag (TIF_SYSCALL_TRACE )) - ret =ptrace_report_syscall_entry (task_pt_regs (current)); + ret = !ptrace_report_syscall_permit_entry (task_pt_regs (current));if (!seccomp_permit_syscall ())return -1 ;
arch/microblaze/kernel/ptrace.c +1 -1
@@ -139,7 +139,7 @@ asmlinkage unsigned long do_syscall_trace_enter(struct pt_regs *regs)secure_computing_strict (regs->r12);if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) + !ptrace_report_syscall_permit_entry (regs))/* * Tracing decided this syscall should not happen. * We'll return a bogus call number to get an ENOSYS
arch/mips/kernel/ptrace.c +1 -1
@@ -1324,7 +1324,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs)user_exit ();if (test_thread_flag (TIF_SYSCALL_TRACE )) { -if (ptrace_report_syscall_entry (regs)) +if (!ptrace_report_syscall_permit_entry (regs))return -1 ; }
arch/nios2/kernel/ptrace.c +1 -1
@@ -133,7 +133,7 @@ asmlinkage int do_syscall_trace_enter(void)int ret =0 ;if (test_thread_flag (TIF_SYSCALL_TRACE )) - ret =ptrace_report_syscall_entry (task_pt_regs (current)); + ret = !ptrace_report_syscall_permit_entry (task_pt_regs (current));return ret; }
arch/openrisc/kernel/ptrace.c +1 -1
@@ -293,7 +293,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)long ret =0 ;if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) + !ptrace_report_syscall_permit_entry (regs))/* * Tracing decided this syscall should not happen. * We'll return a bogus call number to get an ENOSYS
arch/parisc/kernel/ptrace.c +4 -6
@@ -326,7 +326,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,long do_syscall_trace_enter (struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE )) { -int rc =ptrace_report_syscall_entry (regs); +bool permit =ptrace_report_syscall_permit_entry (regs);/* * As tracesys_next does not set %r28 to -ENOSYS
@@ -334,12 +334,10 @@ long do_syscall_trace_enter(struct pt_regs *regs)*/ regs->gr[28 ] = -ENOSYS ; -if (rc) { +if (!permit) {/* -* A nonzero return code from -* ptrace_report_syscall_entry() tells us -* to prevent the syscall execution. Skip -* the syscall call and the syscall restart handling. +* Skip the syscall call and the syscall restart +* handling. * * Note that the tracer may also just change * regs->gr[20] to an invalid syscall number,
arch/sh/kernel/ptrace_32.c +1 -1
@@ -455,7 +455,7 @@ long arch_ptrace(struct task_struct *child, long request,asmlinkage long do_syscall_trace_enter (struct pt_regs *regs) {if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) { + !ptrace_report_syscall_permit_entry (regs)) { regs->regs[0 ] = -ENOSYS ;return -1 ; }
arch/sparc/kernel/ptrace_32.c +1 -1
@@ -441,7 +441,7 @@ asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p)if (syscall_exit_p)ptrace_report_syscall_exit (regs,0 );else - ret =ptrace_report_syscall_entry (regs); + ret = !ptrace_report_syscall_permit_entry (regs); }return ret;
arch/sparc/kernel/ptrace_64.c +1 -1
@@ -1093,7 +1093,7 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)user_exit ();if (test_thread_flag (TIF_SYSCALL_TRACE )) - ret =ptrace_report_syscall_entry (regs); + ret = !ptrace_report_syscall_permit_entry (regs);if (unlikely (test_thread_flag (TIF_SYSCALL_TRACEPOINT )))trace_sys_enter (regs, regs->u_regs[UREG_G1 ]);
arch/um/kernel/ptrace.c +1 -1
@@ -135,7 +135,7 @@ int syscall_trace_enter(struct pt_regs *regs)if (!test_thread_flag (TIF_SYSCALL_TRACE ))return 0 ; -return ptrace_report_syscall_entry (regs); +return !ptrace_report_syscall_permit_entry (regs); }void syscall_trace_leave (struct pt_regs *regs)
arch/xtensa/kernel/ptrace.c +1 -1
@@ -547,7 +547,7 @@ int do_syscall_trace_enter(struct pt_regs *regs) regs->areg[2 ] = -ENOSYS ;if (test_thread_flag (TIF_SYSCALL_TRACE ) && -ptrace_report_syscall_entry (regs)) { + !ptrace_report_syscall_permit_entry (regs)) { regs->areg[2 ] = -ENOSYS ; regs->syscall =NO_SYSCALL ;return 0 ;
include/asm-generic/syscall.h +2 -2
@@ -58,8 +58,8 @@ void syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr);* * It's only valid to call this when @task is stopped for system * call exit tracing (due to %SYSCALL_WORK_SYSCALL_TRACE or -* %SYSCALL_WORK_SYSCALL_AUDIT), after ptrace_report_syscall_entry() -* returned nonzero to prevent the system call from taking place. +* %SYSCALL_WORK_SYSCALL_AUDIT), after ptrace_report_syscall_permit_entry() +* returned False to prevent the system call from taking place. * * This rolls back the register state in @regs so it's as if the * system call instruction was a no-op. The registers containing
include/linux/entry-common.h +12 -13
@@ -39,21 +39,22 @@ SYSCALL_WORK_SYSCALL_EXIT_TRAP)/** -* arch_ptrace_report_syscall_entry - Architecture specific ptrace_report_syscall_entry() wrapper +* arch_ptrace_report_syscall_permit_entry - Architecture specific wrapper for +* ptrace_report_syscall_permit_entry() * @regs: Pointer to the register state at syscall entry * -* Invoked from syscall_trace_enter() to wrap ptrace_report_syscall_entry(). +* Invoked from syscall_trace_enter() to wrap ptrace_report_syscall_permit_entry(). * -* This allows architecture specific ptrace_report_syscall_entry() +* This allows architecture specific ptrace_report_syscall_permit_entry() * implementations. If not defined by the architecture this falls back to -* to ptrace_report_syscall_entry(). +* to ptrace_report_syscall_permit_entry(). */ -static __always_inline int arch_ptrace_report_syscall_entry(struct pt_regs *regs); +static __always_inline bool arch_ptrace_report_syscall_permit_entry(struct pt_regs *regs); -#ifndef arch_ptrace_report_syscall_entry -static __always_inline int arch_ptrace_report_syscall_entry(struct pt_regs *regs) +#ifndef arch_ptrace_report_syscall_permit_entry +static __always_inline bool arch_ptrace_report_syscall_permit_entry(struct pt_regs *regs) { -return ptrace_report_syscall_entry (regs); +return ptrace_report_syscall_permit_entry (regs); }#endif
@@ -73,8 +74,6 @@ static inline void syscall_enter_audit(struct pt_regs *regs, long syscall)static __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work,long syscall) { -long ret =0 ; -/* * Handle Syscall User Dispatch. This must comes first, since * the ABI here can be something that doesn't make sense for
@@ -95,8 +94,8 @@ static __always_inline long syscall_trace_enter(struct pt_regs *regs, unsigned l/* Handle ptrace */ if (work & (SYSCALL_WORK_SYSCALL_TRACE |SYSCALL_WORK_SYSCALL_EMU )) { - ret =arch_ptrace_report_syscall_entry (regs); -if (ret || (work &SYSCALL_WORK_SYSCALL_EMU )) +if (!arch_ptrace_report_syscall_permit_entry (regs) || + (work &SYSCALL_WORK_SYSCALL_EMU ))return -1L ; }
@@ -137,7 +136,7 @@ static __always_inline long syscall_trace_enter(struct pt_regs *regs, unsigned l* It handles the following work items: * * 1) syscall_work flag dependent invocations of -* ptrace_report_syscall_entry(), __seccomp_permit_syscall(), trace_sys_enter() +* ptrace_report_syscall_permit_entry(), __seccomp_permit_syscall(), trace_sys_enter() * 2) Invocation of audit_syscall_entry() */ static __always_inline long syscall_enter_from_user_mode_work (struct pt_regs *regs,long syscall)
include/linux/ptrace.h +6 -7
@@ -405,13 +405,13 @@ extern void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oa/* * ptrace report for syscall entry and exit looks identical. */ -static inline int ptrace_report_syscall (unsigned long message) +static inline bool ptrace_report_syscall (unsigned long message) {int ptrace = current->ptrace;int signr;if (!(ptrace &PT_PTRACED )) -return 0 ; +return true; signr =ptrace_notify (SIGTRAP | ((ptrace &PT_TRACESYSGOOD ) ?0x80 :0 ), message);
@@ -424,11 +424,11 @@ static inline int ptrace_report_syscall(unsigned long message)if (signr)send_sig (signr, current,1 ); -return fatal_signal_pending (current); +return !fatal_signal_pending (current); }/** -* ptrace_report_syscall_entry - task is about to attempt a system call +* ptrace_report_syscall_permit_entry - task is about to attempt a system call * @regs: user register state of current task * * This will be called if %SYSCALL_WORK_SYSCALL_TRACE or
@@ -438,7 +438,7 @@ static inline int ptrace_report_syscall(unsigned long message)* call number and arguments to be tried. It is safe to block here, * preventing the system call from beginning. * -* Returns zero normally, or nonzero if the calling arch code should abort +* Returns True normally, or False if the calling architecture code should abort * the system call. That must prevent normal entry so no system call is * made. If @task ever returns to user mode after this, its register state * is unspecified, but should be something harmless like an %ENOSYS error
@@ -447,8 +447,7 @@ static inline int ptrace_report_syscall(unsigned long message)* * Called without locks, just after entering kernel mode. */ -static inline __must_check int ptrace_report_syscall_entry ( -struct pt_regs *regs) +static inline __must_check bool ptrace_report_syscall_permit_entry (struct pt_regs *regs) {return ptrace_report_syscall (PTRACE_EVENTMSG_SYSCALL_ENTRY ); }
Thomas Gleixner
maintainerPATCH 13/18 entry: Make trace_syscall_enter() return type bool
In reply to Thomas GleixnerIn preparation of converting the return value of syscall_enter_from_user_mode[_work]() bool, rework trace_syscall_enter() to
- update the syscall number via a pointer argument
- Return True if the syscall number is != -1, False otherwise
That aligns with ptrace_report_syscall_permit_enter() and seccomp_permit_syscall().
The only difference is that this also returns False, when the syscall number was already -1 to begin with, but there is not much which can be done about that. As the architecture has to preset the return value to -ENOSYS anyway, that results in the correct return value for such an invalid syscall.
--- include/linux/entry-common.h | 8 +++++--- kernel/entry/syscall-common.c | 7 ++++--- 2 files changed, 9 insertions(+), 6 deletions(-)
include/linux/entry-common.h +5 -3
@@ -58,7 +58,7 @@ static __always_inline bool arch_ptrace_#endif bool syscall_user_dispatch (struct pt_regs *regs); -long trace_syscall_enter (struct pt_regs *regs,long syscall); +bool trace_syscall_enter (struct pt_regs *regs,long *syscall);void trace_syscall_exit (struct pt_regs *regs,long ret);static inline void syscall_enter_audit (struct pt_regs *regs,long syscall)
@@ -108,8 +108,10 @@ static __always_inline long syscall_trac/* Either of the above might have changed the syscall number */ syscall =syscall_get_nr (current, regs); -if (unlikely (work &SYSCALL_WORK_SYSCALL_TRACEPOINT )) - syscall =trace_syscall_enter (regs, syscall); +if (unlikely (work &SYSCALL_WORK_SYSCALL_TRACEPOINT )) { +if (!trace_syscall_enter (regs, &syscall)) +return -1L ; + }syscall_enter_audit (regs, syscall);
kernel/entry/syscall-common.c +4 -3
@@ -7,14 +7,15 @@/* Out of line to prevent tracepoint code duplication */ -long trace_syscall_enter (struct pt_regs *regs,long syscall) +bool trace_syscall_enter (struct pt_regs *regs,long *syscall) { -trace_sys_enter (regs, syscall); +trace_sys_enter (regs, *syscall);/* * Probes or BPF hooks in the tracepoint may have changed the * system call number. Reread it. */ -return syscall_get_nr (current, regs); + *syscall =syscall_get_nr (current, regs); +return *syscall !=-1L ; }void trace_syscall_exit (struct pt_regs *regs,long ret)
Re: [patch 13/18] entry: Make trace_syscall_enter() return type bool
Hello,
Quoted 6 lines · Thomas Gleixner
In preparation of converting the return value of syscall_enter_from_user_mode[_work]() bool, rework
trace_syscall_enter()to- update the syscall number via a pointer argument
- Return True if the syscall number is != -1, False otherwise
This does not achieve the goal of the initial RFC: To detangle the return value of syscall_enter_from_user_mode from the syscall number.
This still conflates them, making it impossible to tell if the syscall was rejected or syscall number was -1 to start with. Now also obfuscated by performing the check deeper inside the common code.
Quoted 8 lines
That aligns with
ptrace_report_syscall_permit_enter()andseccomp_permit_syscall().The only difference is that this also returns False, when the syscall number was already -1 to begin with, but there is not much which can be done about that. As the architecture has to preset the return value to
-ENOSYSanyway, that results in the correct return value for such an invalid syscall.
That's not possible to do for architectures where the syscall number and the syscall return value are in the same register.
You suggested that it is possible to not write the return value into an actual register but use an additional field for that, and have the exit code write the register.
However, that's not what is documented, nor what is currently done.
While this is an improvement in some respects the goal to have clear and intelligible API around the generic entry is not acheived.
Thanks
Michal
Quoted 53 lines
Signed-off-by Thomas Gleixner <[email protected]>--- include/linux/entry-common.h | 8 +++++--- kernel/entry/syscall-common.c | 7 ++++--- 2 files changed, 9 insertions(+), 6 deletions(-)include/linux/entry-common.h +5
-3@@ -58,7 +58,7 @@ static __always_inline bool arch_ptrace_#endif bool syscall_user_dispatch (struct pt_regs *regs); -long trace_syscall_enter (struct pt_regs *regs,long syscall); +bool trace_syscall_enter (struct pt_regs *regs,long *syscall);void trace_syscall_exit (struct pt_regs *regs,long ret);static inline void syscall_enter_audit (struct pt_regs *regs,long syscall)@@ -108,8 +108,10 @@ static __always_inline long syscall_trac/* Either of the above might have changed the syscall number */ syscall =syscall_get_nr (current, regs); -if (unlikely (work &SYSCALL_WORK_SYSCALL_TRACEPOINT )) - syscall =trace_syscall_enter (regs, syscall); +if (unlikely (work &SYSCALL_WORK_SYSCALL_TRACEPOINT )) { +if (!trace_syscall_enter (regs, &syscall)) +return -1L ; + }syscall_enter_audit (regs, syscall);kernel/entry/syscall-common.c +4
-3@@ -7,14 +7,15 @@/* Out of line to prevent tracepoint code duplication */ -long trace_syscall_enter (struct pt_regs *regs,long syscall) +bool trace_syscall_enter (struct pt_regs *regs,long *syscall) { -trace_sys_enter (regs, syscall); +trace_sys_enter (regs, *syscall);/* * Probes or BPF hooks in the tracepoint may have changed the * system call number. Reread it. */ -return syscall_get_nr (current, regs); + *syscall =syscall_get_nr (current, regs); +return *syscall !=-1L ; }void trace_syscall_exit (struct pt_regs *regs,long ret)
Thomas Gleixner
maintainerRe: [patch 13/18] entry: Make trace_syscall_enter() return type bool
Quoted 10 lines · Michal Suchánek
Quoted 6 lines · Thomas Gleixner
In preparation of converting the return value of syscall_enter_from_user_mode[_work]() bool, rework
trace_syscall_enter()to- update the syscall number via a pointer argument
- Return True if the syscall number is != -1, False otherwise
This does not achieve the goal of the initial RFC: To detangle the return value of
syscall_enter_from_user_modefrom the syscall number.
As I explained to you before: Your RFC broke the implicit assumption of tracing, which is way worse than having this oddity.
Quoted 3 lines
This still conflates them, making it impossible to tell if the syscall was rejected or syscall number was -1 to start with. Now also obfuscated by performing the check deeper inside the common code.
That's where it belongs. It's a problem to solve within the given semantics of trace_syscall_enter() and not a problem to be worked around at the call sites if you want to have consolidated semantics.
Quoted 6 lines
Quoted 5 lines
The only difference is that this also returns False, when the syscall number was already -1 to begin with, but there is not much which can be done about that. As the architecture has to preset the return value to
-ENOSYSanyway, that results in the correct return value for such an invalid syscall.
Quoted 8 lines
That's not possible to do for architectures where the syscall number and the syscall return value are in the same register.
You suggested that it is possible to not write the return value into an actual register but use an additional field for that, and have the exit code write the register.
However, that's not what is documented, nor what is currently done.
Just because S390 screwed up their ABI and then on top of that failed to do what _every_ other architecture in the kernel does, i.e. having a result storage which is preset to -ENOSYS does not mean that S390 did the right thing just because it was not documented. Kernel documentation is known to be incomplete and I fixed it up in the last patch as you might have noticed.
Just for the record. Presetting the return value to -ENOSYS has been practice for three decades. I couldn't be bothered to do a full search in the history trees to figure out the exact point, but as of 2.1.9, which was released in Nov. 1996, this is definitely the case.
So don't tell me that because S390 missed the train when it was added to mainline in 2007 (, i.e. 11 years _after_ this "undocumented" rule was established that now 20 years later the world has to revolve around S390 and your personal idea of "clear and intelligible":
Quoted 2 lines
While this is an improvement in some respects the goal to have clear and intelligible API around the generic entry is not acheived.
I'm honestly not sure whether I should laugh or cry.
You are completely missing the point:
1) The set in stone rule is that if the entry code returns -1L as the syscall number then the architecture code has to skip the syscall invocation _and_ is not supposed to change the return value.
2) There is no guarantee and never has been that any of the involved mechanisms (ptrace, seccomp, tracing) will change the return value when it sets the syscall number to -1L.
Quite the contrary there has been a long time (30 years at least) expectation that the return value has been preset to -ENOSYS.
3) It's trivial as demonstrated to make ptrace and seccomp more comprehensible but that does not invalidate #2
4) Due to the historical integration of tracing (+probes/BPF) there is an implicit assumption that the return code is preset to -ENOSYS. See #2
5) There is an obvious ambiguity between the initial syscall number being -1 and the change of syscall number to -1 in the case of tracing, but that's not unique to tracing:
If e.g. seccomp() observes the handed in syscall number to be -1 and tells in the return code to skip the syscall, then it can rightfully assume that the return code will be -ENOSYS and has no obligation to set it explicitly. See #2
Q: Is it perfect?
A: No
Q: Can it be made perfect?
A: No, because you can't change history and established practice.
Just for illustration. Changing the logic in trace_syscall_enter() to:
kernel/entry/syscall-common.c +3 -1
@@ -9,13 +9,15 @@bool trace_syscall_enter (struct pt_regs *regs,long *syscall) { +long orig_syscall = *syscall; +trace_sys_enter (regs, *syscall);/* * Probes or BPF hooks in the tracepoint may have changed the * system call number. Reread it. */ *syscall =syscall_get_nr (current, regs); -return *syscall !=-1L ; +return *syscall == orig_syscall || *syscall !=-1L ; }void trace_syscall_exit (struct pt_regs *regs,long ret)
does not make #2 magically go away. It's still the same problem whether you like it or not.
Thanks,
tglx
---
Ignorance is bliss -- Thomas Gray, 1742
Thomas Gleixner
maintainerRe: [patch 13/18] entry: Make trace_syscall_enter() return type bool
Quoted 29 lines · Thomas Gleixner
On Wed, Jul 08 2026 at 17:52, Michal Suchánek wrote:
Q: Is it perfect?
A: NoQ: Can it be made perfect?
A: No, because you can't change history and established practice.Just for illustration. Changing the logic in
trace_syscall_enter()to:kernel/entry/syscall-common.c +3
-1@@ -9,13 +9,15 @@bool trace_syscall_enter (struct pt_regs *regs,long *syscall) { +long orig_syscall = *syscall; +trace_sys_enter (regs, *syscall);/* * Probes or BPF hooks in the tracepoint may have changed the * system call number. Reread it. */ *syscall =syscall_get_nr (current, regs); -return *syscall !=-1L ; +return *syscall == orig_syscall || *syscall !=-1L ; }void trace_syscall_exit (struct pt_regs *regs,long ret)
Quoted 2 lines
does not make #2 magically go away. It's still the same problem whether you like it or not.
And just to be entirely clear, the syscall() interface has to be correct in the first place, but then it's all about performance.
So the sequence of:
pt_regs = PUSH_REGS();
syscall = pt_regs->syscall_reg;
pt_regs->result = -ENOSYS;
arch_syscall(pt_regs, syscall) {
if (likely(syscall_enter_from_user_mode(pt_regs, &syscall) {
if (syscall < SYSCALL_max)
pt_regs->result = invoke_syscall(pt_regs, syscall);
}
,,,,
}
pt_regs->($RETURN_VALUE) = pt_regs->result;
POP_REGS();
return;is the correct and obviuosly most efficient way idependent of the -1L return value overload in the original implementation, which this series gets rid of for clarity.
If an architecture decide[sd] to do otherwise and makes up it's own rules which only cover parts of the problem then it _is_ an architecture problem and not something which has to be solved by claiming that every architecture has to implement the same nonsense as you falsely claimed in your RFC^WPOC^Whack thread:
"However, the API should be specified in a way that does not require
everyone implementing such flag."
There is _ZERO_ requirement for any architecture to implement that flag. Just because S390 decided it's a brilliant idea to do so does not make it a requirement for everyone.
No. Every other architecture got it right because they looked at the historical patterns despite having correct documentation at hand.
Feel free to prove me wrong with actual facts.
Thanks,
tglx
Re: [patch 13/18] entry: Make trace_syscall_enter() return type bool
Quoted 36 lines · On Thu, 09 Jul 2026 01:14:24 +0200 Thomas Gleixner <[email protected]> wrote:
Quoted 29 lines · Thomas Gleixner
On Wed, Jul 08 2026 at 17:52, Michal Suchánek wrote:
Q: Is it perfect?
A: NoQ: Can it be made perfect?
A: No, because you can't change history and established practice.Just for illustration. Changing the logic in
trace_syscall_enter()to:kernel/entry/syscall-common.c +3
-1@@ -9,13 +9,15 @@bool trace_syscall_enter (struct pt_regs *regs,long *syscall) { +long orig_syscall = *syscall; +trace_sys_enter (regs, *syscall);/* * Probes or BPF hooks in the tracepoint may have changed the * system call number. Reread it. */ *syscall =syscall_get_nr (current, regs); -return *syscall !=-1L ; +return *syscall == orig_syscall || *syscall !=-1L ; }void trace_syscall_exit (struct pt_regs *regs,long ret)Quoted 2 lines
does not make #2 magically go away. It's still the same problem whether you like it or not.
And just to be entirely clear, the
syscall()interface has to be correct in the first place, but then it's all about performance.
Quoted 8 lines
So the sequence of:
pt_regs = PUSH_REGS(); syscall = pt_regs->syscall_reg; pt_regs->result = -ENOSYS; arch_syscall(pt_regs, syscall) { if (likely(syscall_enter_from_user_mode(pt_regs, &syscall) {
I guess most architectures inline that to avoid the &syscall. Otherwise you'd want:
syscall = syscall_enter_from_user_mode(pt_regs, syscall);
with the 'error' return being selected to fail the test below (which -1L converted to ~0UL will do nicely).
David
Quoted 35 lines
if (syscall < SYSCALL_max) pt_regs->result = invoke_syscall(pt_regs, syscall); } ,,,, } pt_regs->($RETURN_VALUE) = pt_regs->result; POP_REGS(); return;is the correct and obviuosly most efficient way idependent of the -1L return value overload in the original implementation, which this series gets rid of for clarity.
If an architecture decide[sd] to do otherwise and makes up it's own rules which only cover parts of the problem then it _is_ an architecture problem and not something which has to be solved by claiming that every architecture has to implement the same nonsense as you falsely claimed in your RFC^WPOC^Whack thread:
"However, the API should be specified in a way that does not require
everyone implementing such flag."There is _ZERO_ requirement for any architecture to implement that flag. Just because S390 decided it's a brilliant idea to do so does not make it a requirement for everyone.
No. Every other architecture got it right because they looked at the historical patterns despite having correct documentation at hand.
Feel free to prove me wrong with actual facts.
Thanks,
tglx
Re: [patch 13/18] entry: Make trace_syscall_enter() return type bool
In reply to Thomas GleixnerQuoted 7 lines · Thomas Gleixner
Quoted 6 lines · Michal Suchánek
Quoted 5 lines · Thomas Gleixner
In preparation of converting the return value of syscall_enter_from_user_mode[_work]() bool, rework
trace_syscall_enter()to- update the syscall number via a pointer argument
Quoted 7 lines
Quoted 4 lines
Quoted 1 line
- Return True if the syscall number is != -1, False otherwise
This does not achieve the goal of the initial RFC: To detangle the return value of
syscall_enter_from_user_modefrom the syscall number.As I explained to you before: Your RFC broke the implicit assumption of tracing, which is way worse than having this oddity.
It would be so nice to make the assumptions about the entry API explicit so that platforms can agree on the semantics.
Quoted 31 lines
Quoted 4 lines
This still conflates them, making it impossible to tell if the syscall was rejected or syscall number was -1 to start with. Now also obfuscated by performing the check deeper inside the common code.
That's where it belongs. It's a problem to solve within the given semantics of
trace_syscall_enter()and not a problem to be worked around at the call sites if you want to have consolidated semantics.Quoted 6 lines
Quoted 5 lines
The only difference is that this also returns False, when the syscall number was already -1 to begin with, but there is not much which can be done about that. As the architecture has to preset the return value to
-ENOSYSanyway, that results in the correct return value for such an invalid syscall.Quoted 8 lines
That's not possible to do for architectures where the syscall number and the syscall return value are in the same register.
You suggested that it is possible to not write the return value into an actual register but use an additional field for that, and have the exit code write the register.
However, that's not what is documented, nor what is currently done.
Just because S390 screwed up their ABI and then on top of that failed to do what _every_ other architecture in the kernel does, i.e. having a result storage which is preset to
-ENOSYSdoes not mean that S390 did the right thing just because it was not documented. Kernel documentation is known to be incomplete and I fixed it up in the last patch as you might have noticed.
Quoted 2 lines
Just for the record. Presetting the return value to
-ENOSYShas been practice for three decades. I couldn't be bothered to do a full search
No, it isn't practice anymore for decades.
The moment ppc and s390 support was merged they do not preset the syscall return value to -ENOSYS, for obvious reason.
That is how the undocumented, implicit, 'as implemented' API goes. It silently changes as the implementation evolves.
Quoted 7 lines
in the history trees to figure out the exact point, but as of 2.1.9, which was released in Nov. 1996, this is definitely the case.
So don't tell me that because S390 missed the train when it was added to mainline in 2007 (, i.e. 11 years _after_ this "undocumented" rule was established that now 20 years later the world has to revolve around S390 and your personal idea of "clear and intelligible":
Don't tell me you missed the train on what the actual API of syscall entry is.
Quoted 11 lines
Quoted 3 lines
While this is an improvement in some respects the goal to have clear and intelligible API around the generic entry is not acheived.
I'm honestly not sure whether I should laugh or cry.
You are completely missing the point:
1) The set in stone rule is that if the entry code returns -1L as the syscall number then the architecture code has to skip the syscall invocation _and_ is not supposed to change the return value.
Which stone?
Pics or it did not happen.
Quoted 4 lines
2) There is no guarantee and never has been that any of the involved mechanisms (ptrace, seccomp, tracing) will change the return value when it sets the syscall number to -1L.
For ptrace to correctly emulate a syscall it needs to set the syscall nr to an invalid value on entry, and the desired result if the syscall on exit AFAICT.
Relying on platfrom quirk to assume that the return valu is set to ENOSYS is insufficient.
I doubt many platfroms have an ABI that dictates that the register that has the syscal nr is set to -1 on exit from syscal. Then even if the -ENOSYS is preset by the kernel the syscall nr needs to be poked back on exit for the emulation to be correct.
Quoted 3 lines
Quite the contrary there has been a long time (30 years at least) expectation that the return value has been preset to
-ENOSYS.
That is your opinion, not the fact. Multiple platforms do not work like that.
Quoted 7 lines
3) It's trivial as demonstrated to make ptrace and seccomp more comprehensible but that does not invalidate #2
4) Due to the historical integration of tracing (+probes/BPF) there is an implicit assumption that the return code is preset to
-ENOSYS. See #2
False again
Quoted 9 lines
5) There is an obvious ambiguity between the initial syscall number being -1 and the change of syscall number to -1 in the case of tracing, but that's not unique to tracing:
If e.g.
seccomp()observes the handed in syscall number to be -1 and tells in the return code to skip the syscall, then it can rightfully assume that the return code will be-ENOSYSand has no obligation to set it explicitly. See #2
False again
Quoted 29 lines
Q: Is it perfect?
A: NoQ: Can it be made perfect?
A: No, because you can't change history and established practice.Just for illustration. Changing the logic in
trace_syscall_enter()to:kernel/entry/syscall-common.c +3
-1@@ -9,13 +9,15 @@bool trace_syscall_enter (struct pt_regs *regs,long *syscall) { +long orig_syscall = *syscall; +trace_sys_enter (regs, *syscall);/* * Probes or BPF hooks in the tracepoint may have changed the * system call number. Reread it. */ *syscall =syscall_get_nr (current, regs); -return *syscall !=-1L ; +return *syscall == orig_syscall || *syscall !=-1L ; }void trace_syscall_exit (struct pt_regs *regs,long ret)
Quoted 2 lines
does not make #2 magically go away. It's still the same problem whether you like it or not.
However, reading the syscall number from pt_regs only after syscall_enter_from_user_mode exits does.
Thanks
Michal
Oleg Nesterov
maintainerRe: [patch 13/18] entry: Make trace_syscall_enter() return type bool
Quoted 12 lines · Michal Suchánek
Quoted 4 lines · Thomas Gleixner
1) The set in stone rule is that if the entry code returns -1L as the syscall number then the architecture code has to skip the syscall invocation _and_ is not supposed to change the return value.
Which stone?
Pics or it did not happen.
Quoted 1 line
Quoted 7 lines
Quoted 3 lines
2) There is no guarantee and never has been that any of the involved mechanisms (ptrace, seccomp, tracing) will change the return value when it sets the syscall number to -1L.
For ptrace to correctly emulate a syscall it needs to set the syscall nr to an invalid value on entry, and the desired result if the syscall on exit AFAICT.
I can only say that ptrace users do want to skip the syscall and set the return value on entry.
See
[PATCH v5 1/2] ptrace: add PTRACE_SET_SYSCALL_INFO syscall skipping support https://lore.kernel.org/all/[email protected]/
The changelog explains that currently this doesn't work because among the arches which define HAVE_ARCH_TRACEHOOK (at least) arch/mips is broken in this regard.
Oleg.
Re: [patch 13/18] entry: Make trace_syscall_enter() return type bool
Quoted 24 lines · Oleg Nesterov
Quoted 12 lines · Michal Suchánek
Quoted 4 lines · Thomas Gleixner
1) The set in stone rule is that if the entry code returns -1L as the syscall number then the architecture code has to skip the syscall invocation _and_ is not supposed to change the return value.
Which stone?
Pics or it did not happen.
Quoted 1 line
Quoted 7 lines
Quoted 3 lines
2) There is no guarantee and never has been that any of the involved mechanisms (ptrace, seccomp, tracing) will change the return value when it sets the syscall number to -1L.
For ptrace to correctly emulate a syscall it needs to set the syscall nr to an invalid value on entry, and the desired result if the syscall on exit AFAICT.
I can only say that ptrace users do want to skip the syscall and set the return value on entry.
Quoted 7 lines
See
[PATCH v5 1/2] ptrace: add PTRACE_SET_SYSCALL_INFO syscall skipping support https://lore.kernel.org/all/[email protected]/The changelog explains that currently this doesn't work because among the arches which define
HAVE_ARCH_TRACEHOOK(at least)arch/mipsis broken in this regard.
Or it could be documented that setting the return value has to be done in the exit trace, and that would than work on any architecture AFAICT.
With ppc and s390 using the same register for the syscall number and syscall return value it's very much impossible to poke the return value on entry into a register using the generic register access function. As of now there is no place to store the value ot of the return value outside of the registers, either.
And the current PTRACE_SET_SYSCALL_INFO indeed sets the syscall nr and arguments on entry and the syscall return value on exit, that disctincion is implemented.
Not sure how the patchset you point out is relevant, it only adds changes in the exit case.
Thanks
Michal
Oleg Nesterov
maintainerRe: [patch 13/18] entry: Make trace_syscall_enter() return type bool
Quoted 10 lines · Michal Suchánek
Quoted 8 lines · Oleg Nesterov
I can only say that ptrace users do want to skip the syscall and set the return value on entry.
See
[PATCH v5 1/2] ptrace: add PTRACE_SET_SYSCALL_INFO syscall skipping support https://lore.kernel.org/all/[email protected]/
Quoted 6 lines
Quoted 3 lines
The changelog explains that currently this doesn't work because among the arches which define
HAVE_ARCH_TRACEHOOK(at least)arch/mipsis broken in this regard.Or it could be documented that setting the return value has to be done in the exit trace, and that would than work on any architecture AFAICT.
Well, ptrace users know the problem. And this what they have to do currently.
Quoted 5 lines
With ppc and s390 using the same register for the syscall number and syscall return value it's very much impossible to poke the return value on entry into a register using the generic register access function. As of now there is no place to store the value ot of the return value outside of the registers, either.
I know nothing about ppc and s390. Can't comment right now.
Quoted 6 lines
And the current
PTRACE_SET_SYSCALL_INFOindeed sets the syscall nr and arguments on entry and the syscall return value on exit, that disctincion is implemented.Not sure how the patchset you point out is relevant, it only adds changes in the exit case.
No. It allows to skip-and-set-retval on PTRACE_EVENT_SECCOMP.
But ENTRY -> EXIT transition is not yet allowed due to the problems above.
Oleg.
Re: [patch 13/18] entry: Make trace_syscall_enter() return type bool
Quoted 29 lines · Oleg Nesterov
Quoted 10 lines · Michal Suchánek
Quoted 8 lines · Oleg Nesterov
I can only say that ptrace users do want to skip the syscall and set the return value on entry.
See
[PATCH v5 1/2] ptrace: add PTRACE_SET_SYSCALL_INFO syscall skipping support https://lore.kernel.org/all/[email protected]/Quoted 6 lines
Quoted 3 lines
The changelog explains that currently this doesn't work because among the arches which define
HAVE_ARCH_TRACEHOOK(at least)arch/mipsis broken in this regard.Or it could be documented that setting the return value has to be done in the exit trace, and that would than work on any architecture AFAICT.
Well, ptrace users know the problem. And this what they have to do currently.
Quoted 5 lines
With ppc and s390 using the same register for the syscall number and syscall return value it's very much impossible to poke the return value on entry into a register using the generic register access function. As of now there is no place to store the value ot of the return value outside of the registers, either.
I know nothing about ppc and s390. Can't comment right now.
Quoted 8 lines
Quoted 6 lines
And the current
PTRACE_SET_SYSCALL_INFOindeed sets the syscall nr and arguments on entry and the syscall return value on exit, that disctincion is implemented.Not sure how the patchset you point out is relevant, it only adds changes in the exit case.
No. It allows to skip-and-set-retval on
PTRACE_EVENT_SECCOMP.
And if it was hooked correctly to seccomp indicating to seccomp that the syscall needs to be skipped it could work but it is not, and will fail on ppc.
Thanks
Michal
Quoted 6 lines
But ENTRY -> EXIT transition is not yet allowed due to the problems above.
Oleg.
Thomas Gleixner
maintainerRe: [patch 13/18] entry: Make trace_syscall_enter() return type bool
In reply to Michal SuchánekMichal!
Quoted 6 lines · Michal Suchánek
Quoted 2 lines · Thomas Gleixner
does not make #2 magically go away. It's still the same problem whether you like it or not.
However, reading the syscall number from
pt_regsonly aftersyscall_enter_from_user_modeexits does.
That does not solve anything at all.
TBH, your communication style is annoying as hell. You fail to provide any useful arguments and explanations despite me giving you a proper analysis. And I'm absolutely tired of this.
So let me try again for _ONE_ last time to explain you why your ppc/s390 world view is broken and let's look at the current code (irrelevant portions omitted).
static __always_inline long syscall_trace_enter(struct pt_regs *regs, unsigned long work)
{
if (work & SYSCALL_WORK_SYSCALL_USER_DISPATCH) {
#1 if (syscall_user_dispatch(regs))
return -1L;
}
if (work & (SYSCALL_WORK_SYSCALL_TRACE | SYSCALL_WORK_SYSCALL_EMU)) {
#2 ret = arch_ptrace_report_syscall_entry(regs);
if (ret || (work & SYSCALL_WORK_SYSCALL_EMU))
return -1L;
}
/* Do seccomp after ptrace, to catch any tracer changes. */
if (work & SYSCALL_WORK_SECCOMP) {
#3 ret = __secure_computing();
if (ret == -1L)
return ret;
}
/* Either of the above might have changed the syscall number */#4 syscall = syscall_get_nr(current, regs);
if (unlikely(work & SYSCALL_WORK_SYSCALL_TRACEPOINT))
#5 syscall = trace_syscall_enter(regs, syscall);
return syscall; }
#1) The user dispatch mechanism does not modify the syscall return
value, but it can rollback the syscall and tell the call site to skip the invocation.
The mechanism used in upstream today is to return -1L as the syscall number which makes the architecture specific entry code skip the syscall and refrain from touching the return value.
#2) ptrace
ptrace can poke whatever it wants into the syscall number storage via ptrace_set_syscall_info_entry() -> syscall_set_nr()
It does not set the return code.
It does not abort the syscall when the poked syscall number is -1L.
It only aborts when a fatal signal is pending.
#3) seccomp
seccomp reads the syscall number, which might have been modified by ptrace and acts upon it.
It can rewrite the syscall number even if it is -1 to begin with.
It can rewrite the return code if it decides to refuse the syscall to be executed.
If it refuses the syscall to be executed it returns -1L.
#4) Rereading the syscall number after ptrace/seccomp
That's required to give the eventually modified number to the tracer.
Obviously the tracer could do that on it's own, but with the current implementation it expects the eventually modified syscall number
Changing that to make the tracer do it, is possible but does not change any of the actual expectations. That's just cosmetic wankery.
#5) tracing
tracing can have a probe or bpf attached, which in turn can
- rewrite the syscall number
- set the return code in case that it sets the syscall number to -1L
It can even set it in case it sets it to some other value, but the architecture code has to be resilent against that no matter what.
- if it does not set the return code when it sets the syscall number to -1L then it has a historical expectation that the syscall returns -ENOSYS
That's how it is and you can argue in circles and it's not going away unless you have a great argument why you can break existing user space probes/bpf scripts.
So now please provide in coherent sentences the argument why this solves anything:
Quoted 2 lines
However, reading the syscall number from
pt_regsonly aftersyscall_enter_from_user_modeexits does.
If you can, which I doubt, then please send a patch [series] against:
git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git entry/rework
with proper change logs explaining the superiour solution.
If not, please spare us the next set of incoherent "I wan't a pony" mails.
Thanks,
tglx
Re: [patch 13/18] entry: Make trace_syscall_enter() return type bool
Quoted 57 lines · Thomas Gleixner
Michal!
Quoted 6 lines · Michal Suchánek
Quoted 2 lines · Thomas Gleixner
does not make #2 magically go away. It's still the same problem whether you like it or not.
However, reading the syscall number from
pt_regsonly aftersyscall_enter_from_user_modeexits does.That does not solve anything at all.
TBH, your communication style is annoying as hell. You fail to provide any useful arguments and explanations despite me giving you a proper analysis. And I'm absolutely tired of this.
So let me try again for _ONE_ last time to explain you why your ppc/s390 world view is broken and let's look at the current code (irrelevant portions omitted).
static
__always_inlinelongsyscall_trace_enter(struct pt_regs *regs, unsigned long work){ if (work & SYSCALL_WORK_SYSCALL_USER_DISPATCH) { #1 if (syscall_user_dispatch(regs)) return -1L; } if (work & (SYSCALL_WORK_SYSCALL_TRACE | SYSCALL_WORK_SYSCALL_EMU)) { #2 ret = arch_ptrace_report_syscall_entry(regs); if (ret || (work & SYSCALL_WORK_SYSCALL_EMU)) return -1L; } /* Do seccomp after ptrace, to catch any tracer changes. */ if (work & SYSCALL_WORK_SECCOMP) { #3 ret = __secure_computing(); if (ret == -1L) return ret; } /* Either of the above might have changed the syscall number */#4 syscall =
syscall_get_nr(current, regs);if (
unlikely(work & SYSCALL_WORK_SYSCALL_TRACEPOINT))
#5 syscall =trace_syscall_enter(regs, syscall);return syscall; }#1) The user dispatch mechanism does not modify the syscall return
value, but it can rollback the syscall and tell the call site to skip the invocation.The mechanism used in upstream today is to return -1L as the syscall number which makes the architecture specific entry code skip the syscall and refrain from touching the return value.
Quoted 8 lines
#2) ptrace
ptrace can poke whatever it wants into the syscall number storage via
ptrace_set_syscall_info_entry()->syscall_set_nr()It does not set the return code.
It does not abort the syscall when the poked syscall number is -1L.
Indeed, it does not abort on -1 syscall number anymore although there are still comments around that claim that setting the syscall number to -1 is special.
Thanks
Michal
Thomas Gleixner
maintainerPATCH 14/18 entry: Make return type of syscall_trace_enter() bool
In reply to Thomas GleixnerThis prepares for changing the return types of syscall_enter_from_user_mode[_work]() to bool, which in turn separates the decision of invoking the syscall from the syscall number, which might have been changed in the call by ptrace, seccomp, tracing.
--- include/linux/entry-common.h | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
include/linux/entry-common.h +15 -13
@@ -71,8 +71,8 @@ static inline void syscall_enter_audit(s } } -static __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work, -long syscall) +static __always_inline bool syscall_trace_enter(struct pt_regs *regs, unsigned long work, +long *syscall) {/* * Handle Syscall User Dispatch. This must comes first, since
@@ -81,7 +81,7 @@ static __always_inline long syscall_trac*/ if (work &SYSCALL_WORK_SYSCALL_USER_DISPATCH ) {if (syscall_user_dispatch (regs)) -return -1L ; +return false; }/*
@@ -90,32 +90,32 @@ static __always_inline long syscall_trac* through hrtimer_interrupt(). */ if (work &SYSCALL_WORK_SYSCALL_RSEQ_SLICE ) -rseq_syscall_enter_work (syscall); +rseq_syscall_enter_work (*syscall);/* Handle ptrace */ if (work & (SYSCALL_WORK_SYSCALL_TRACE |SYSCALL_WORK_SYSCALL_EMU )) {if (!arch_ptrace_report_syscall_permit_entry (regs) || (work &SYSCALL_WORK_SYSCALL_EMU )) -return -1L ; +return false; }/* Do seccomp after ptrace, to catch any tracer changes. */ if (work &SYSCALL_WORK_SECCOMP ) {if (!__seccomp_permit_syscall ()) -return -1L ; +return false; }/* Either of the above might have changed the syscall number */ - syscall =syscall_get_nr (current, regs); + *syscall =syscall_get_nr (current, regs);if (unlikely (work &SYSCALL_WORK_SYSCALL_TRACEPOINT )) { -if (!trace_syscall_enter (regs, &syscall)) -return -1L ; +if (!trace_syscall_enter (regs, syscall)) +return false; } -syscall_enter_audit (regs, syscall); +syscall_enter_audit (regs, *syscall); -return syscall; +return true; }/**
@@ -145,8 +145,10 @@ static __always_inline long syscall_ente {unsigned long work =READ_ONCE (current_thread_info ()->syscall_work); -if (work &SYSCALL_WORK_ENTER ) - syscall =syscall_trace_enter (regs, work, syscall); +if (work &SYSCALL_WORK_ENTER ) { +if (!syscall_trace_enter (regs, work, &syscall)) +return -1L ; + }return syscall; }
Re: [patch 14/18] entry: Make return type of syscall_trace_enter() bool
Quoted 77 lines · Thomas Gleixner
This prepares for changing the return types of syscall_enter_from_user_mode[_work]() to bool, which in turn separates the decision of invoking the syscall from the syscall number, which might have been changed in the call by ptrace, seccomp, tracing.
Signed-off-by Thomas Gleixner <[email protected]>--- include/linux/entry-common.h | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)include/linux/entry-common.h +11
-11@@ -71,8 +71,8 @@ static inline void syscall_enter_audit(s } } -static __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work, -long syscall) +static __always_inline bool syscall_trace_enter(struct pt_regs *regs, unsigned long work, +long *syscall) {/* * Handle Syscall User Dispatch. This must comes first, since @@ -81,7 +81,7 @@ static __always_inline long syscall_trac*/ if (work &SYSCALL_WORK_SYSCALL_USER_DISPATCH ) {if (syscall_user_dispatch (regs)) -return -1L ; +return false; }/* @@ -90,32 +90,32 @@ static __always_inline long syscall_trac* through hrtimer_interrupt(). */ if (work &SYSCALL_WORK_SYSCALL_RSEQ_SLICE ) -rseq_syscall_enter_work (syscall); +rseq_syscall_enter_work (*syscall);/* Handle ptrace */ if (work & (SYSCALL_WORK_SYSCALL_TRACE |SYSCALL_WORK_SYSCALL_EMU )) {if (!arch_ptrace_report_syscall_permit_entry (regs) || (work &SYSCALL_WORK_SYSCALL_EMU )) -return -1L ; +return false; }/* Do seccomp after ptrace, to catch any tracer changes. */ if (work &SYSCALL_WORK_SECCOMP ) {if (!__seccomp_permit_syscall ()) -return -1L ; +return false; }/* Either of the above might have changed the syscall number */ - syscall =syscall_get_nr (current, regs); + *syscall =syscall_get_nr (current, regs);if (unlikely (work &SYSCALL_WORK_SYSCALL_TRACEPOINT )) { -if (!trace_syscall_enter (regs, &syscall)) -return -1L ; +if (!trace_syscall_enter (regs, syscall)) +return false; } -syscall_enter_audit (regs, syscall); +syscall_enter_audit (regs, *syscall); -return syscall; +return true; }/** @@ -145,8 +145,10 @@ static __always_inline long syscall_ente {unsigned long work =READ_ONCE (current_thread_info ()->syscall_work);
include/linux/entry-common.h static __always_inline long syscall_ente · line 154
Quoted 10 lines
include/linux/entry-common.h +4
-2-if (work &SYSCALL_WORK_ENTER ) - syscall =syscall_trace_enter (regs, work, syscall); +if (work &SYSCALL_WORK_ENTER ) { +if (!syscall_trace_enter (regs, work, &syscall)) +return -1L ; + }return syscall; }
Thomas Gleixner
maintainerPATCH 15/18 x86/entry: Make syscall functions static
In reply to Thomas GleixnerThey are only used in the respective source files. No point in exposing them.
--- arch/x86/entry/syscall_32.c | 2 +- arch/x86/entry/syscall_64.c | 10 ++++++---- arch/x86/include/asm/syscall.h | 8 -------- 3 files changed, 7 insertions(+), 13 deletions(-)
arch/x86/entry/syscall_32.c +1 -1
@@ -41,7 +41,7 @@ const sys_call_ptr_t sys_call_table[] =#endif #define __SYSCALL (nr, sym) case nr: return __ia32_##sym(regs); -long ia32_sys_call (const struct pt_regs *regs,unsigned int nr) +static noinline long ia32_sys_call (const struct pt_regs *regs,unsigned int nr) {switch (nr) {#include <asm/syscalls_32.h>
arch/x86/entry/syscall_64.c +6 -4
@@ -32,7 +32,7 @@ const sys_call_ptr_t sys_call_table[] =#undef __SYSCALL#define __SYSCALL (nr, sym) case nr: return __x64_##sym(regs); -long x64_sys_call (const struct pt_regs *regs,unsigned int nr) +static noinline long x64_sys_call (const struct pt_regs *regs,unsigned int nr) {switch (nr) {#include <asm/syscalls_64.h>
@@ -40,15 +40,17 @@ long x64_sys_call(const struct pt_regs * } } -#ifdef CONFIG_X86_X32_ABI -long x32_sys_call (const struct pt_regs *regs,unsigned int nr) +static noinline long x32_sys_call (const struct pt_regs *regs,unsigned int nr) { +#ifdef CONFIG_X86_X32_ABI switch (nr) {#include <asm/syscalls_x32.h> default :return __x64_sys_ni_syscall (regs); } -} +#else +return -ENOSYS ;#endif +} static __always_inline bool do_syscall_x64(struct pt_regs *regs, int nr) {
arch/x86/include/asm/syscall.h +0 -8
@@ -21,14 +21,6 @@ typedef long (*sys_call_ptr_t)(const strextern const sys_call_ptr_t sys_call_table[];/* -* These may not exist, but still put the prototypes in so we -* can use IS_ENABLED(). -*/ -extern long ia32_sys_call (const struct pt_regs *,unsigned int nr); -extern long x32_sys_call (const struct pt_regs *,unsigned int nr); -extern long x64_sys_call (const struct pt_regs *,unsigned int nr); - -/* * Only the low 32 bits of orig_ax are meaningful, so we return int. * This importantly ignores the high bits on 64-bit, so comparisons * sign-extend the low 32 bits.
Re: [patch 15/18] x86/entry: Make syscall functions static
Quoted 56 lines · Thomas Gleixner
They are only used in the respective source files. No point in exposing them.
Signed-off-by Thomas Gleixner <[email protected]>--- arch/x86/entry/syscall_32.c | 2 +- arch/x86/entry/syscall_64.c | 10 ++++++---- arch/x86/include/asm/syscall.h | 8 -------- 3 files changed, 7 insertions(+), 13 deletions(-)arch/x86/entry/syscall_32.c +1
-1@@ -41,7 +41,7 @@ const sys_call_ptr_t sys_call_table[] =#endif #define __SYSCALL (nr, sym) case nr: return __ia32_##sym(regs); -long ia32_sys_call (const struct pt_regs *regs,unsigned int nr) +static noinline long ia32_sys_call (const struct pt_regs *regs,unsigned int nr) {switch (nr) {#include <asm/syscalls_32.h> arch/x86/entry/syscall_64.c +6
-4@@ -32,7 +32,7 @@ const sys_call_ptr_t sys_call_table[] =#undef __SYSCALL#define __SYSCALL (nr, sym) case nr: return __x64_##sym(regs); -long x64_sys_call (const struct pt_regs *regs,unsigned int nr) +static noinline long x64_sys_call (const struct pt_regs *regs,unsigned int nr) {switch (nr) {#include <asm/syscalls_64.h> @@ -40,15 +40,17 @@ long x64_sys_call(const struct pt_regs * } } -#ifdef CONFIG_X86_X32_ABI -long x32_sys_call (const struct pt_regs *regs,unsigned int nr) +static noinline long x32_sys_call (const struct pt_regs *regs,unsigned int nr) { +#ifdef CONFIG_X86_X32_ABI switch (nr) {#include <asm/syscalls_x32.h> default :return __x64_sys_ni_syscall (regs); } -} +#else +return -ENOSYS ;#endif +} static __always_inline bool do_syscall_x64(struct pt_regs *regs, int nr) {
arch/x86/include/asm/syscall.h typedef long (*sys_call_ptr_t)(const str · line 30
Quoted 10 lines
arch/x86/include/asm/syscall.h +0
-7@@ -21,14 +21,6 @@ typedef long (*sys_call_ptr_t)(const strextern const sys_call_ptr_t sys_call_table[];/* -* These may not exist, but still put the prototypes in so we -* can use IS_ENABLED(). -*/ -extern long ia32_sys_call (const struct pt_regs *,unsigned int nr); -extern long x32_sys_call (const struct pt_regs *,unsigned int nr); -extern long x64_sys_call (const struct pt_regs *,unsigned int nr); -
Quoted 5 lines
arch/x86/include/asm/syscall.h +0
-1-/* * Only the low 32 bits of orig_ax are meaningful, so we return int. * This importantly ignores the high bits on 64-bit, so comparisons * sign-extend the low 32 bits.
Re: [patch 15/18] x86/entry: Make syscall functions static
In reply to Thomas GleixnerQuoted 61 lines · Thomas Gleixner
They are only used in the respective source files. No point in exposing them.
Signed-off-by Thomas Gleixner <[email protected]>--- arch/x86/entry/syscall_32.c | 2 +- arch/x86/entry/syscall_64.c | 10 ++++++---- arch/x86/include/asm/syscall.h | 8 -------- 3 files changed, 7 insertions(+), 13 deletions(-)arch/x86/entry/syscall_32.c +1
-1@@ -41,7 +41,7 @@ const sys_call_ptr_t sys_call_table[] =#endif #define __SYSCALL (nr, sym) case nr: return __ia32_##sym(regs); -long ia32_sys_call (const struct pt_regs *regs,unsigned int nr) +static noinline long ia32_sys_call (const struct pt_regs *regs,unsigned int nr) {switch (nr) {#include <asm/syscalls_32.h> arch/x86/entry/syscall_64.c +6
-4@@ -32,7 +32,7 @@ const sys_call_ptr_t sys_call_table[] =#undef __SYSCALL#define __SYSCALL (nr, sym) case nr: return __x64_##sym(regs); -long x64_sys_call (const struct pt_regs *regs,unsigned int nr) +static noinline long x64_sys_call (const struct pt_regs *regs,unsigned int nr) {switch (nr) {#include <asm/syscalls_64.h> @@ -40,15 +40,17 @@ long x64_sys_call(const struct pt_regs * } } -#ifdef CONFIG_X86_X32_ABI -long x32_sys_call (const struct pt_regs *regs,unsigned int nr) +static noinline long x32_sys_call (const struct pt_regs *regs,unsigned int nr) { +#ifdef CONFIG_X86_X32_ABI switch (nr) {#include <asm/syscalls_x32.h> default :return __x64_sys_ni_syscall (regs); } -} +#else +return -ENOSYS ;#endif +} static __always_inline bool do_syscall_x64(struct pt_regs *regs, int nr) {arch/x86/include/asm/syscall.h +0
-1@@ -21,14 +21,6 @@ typedef long (*sys_call_ptr_t)(const strextern const sys_call_ptr_t sys_call_table[];/* -* These may not exist, but still put the prototypes in so we
arch/x86/include/asm/syscall.h typedef long (*sys_call_ptr_t)(const str · line 26
Quoted 10 lines
arch/x86/include/asm/syscall.h +0
-7-* can use IS_ENABLED(). -*/ -extern long ia32_sys_call (const struct pt_regs *,unsigned int nr); -extern long x32_sys_call (const struct pt_regs *,unsigned int nr); -extern long x64_sys_call (const struct pt_regs *,unsigned int nr); - -/* * Only the low 32 bits of orig_ax are meaningful, so we return int. * This importantly ignores the high bits on 64-bit, so comparisons * sign-extend the low 32 bits.
[tip: core/entry] x86/entry: Make syscall functions static
In reply to Thomas GleixnerThe following commit has been merged into the core/entry branch of tip:
The following commit has been merged into the core/entry branch of tip:
Commit-ID: 2b341c74dbf8864b6dd32119b761ceaab516249e Gitweb: https://git.kernel.org/tip/2b341c74dbf8864b6dd32119b761ceaab516249e Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 07 Jul 2026 21:06:57 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Sun, 12 Jul 2026 12:38:02 +02:00
x86/entry: Make syscall functions static
They are only used in the respective source files. No point in exposing them.
--- arch/x86/entry/syscall_32.c | 2 +- arch/x86/entry/syscall_64.c | 10 ++++++---- arch/x86/include/asm/syscall.h | 8 -------- 3 files changed, 7 insertions(+), 13 deletions(-)
arch/x86/entry/syscall_32.c +1 -1
@@ -41,7 +41,7 @@ const sys_call_ptr_t sys_call_table[] = {#endif #define __SYSCALL (nr, sym) case nr: return __ia32_##sym(regs); -long ia32_sys_call (const struct pt_regs *regs,unsigned int nr) +static noinline long ia32_sys_call (const struct pt_regs *regs,unsigned int nr) {switch (nr) {#include <asm/syscalls_32.h>
arch/x86/entry/syscall_64.c +6 -4
@@ -32,7 +32,7 @@ const sys_call_ptr_t sys_call_table[] = {#undef __SYSCALL#define __SYSCALL (nr, sym) case nr: return __x64_##sym(regs); -long x64_sys_call (const struct pt_regs *regs,unsigned int nr) +static noinline long x64_sys_call (const struct pt_regs *regs,unsigned int nr) {switch (nr) {#include <asm/syscalls_64.h>
@@ -40,15 +40,17 @@ long x64_sys_call(const struct pt_regs *regs, unsigned int nr) } } -#ifdef CONFIG_X86_X32_ABI -long x32_sys_call (const struct pt_regs *regs,unsigned int nr) +static noinline long x32_sys_call (const struct pt_regs *regs,unsigned int nr) { +#ifdef CONFIG_X86_X32_ABI switch (nr) {#include <asm/syscalls_x32.h> default :return __x64_sys_ni_syscall (regs); } -} +#else +return -ENOSYS ;#endif +} static __always_inline bool do_syscall_x64(struct pt_regs *regs, int nr) {
arch/x86/include/asm/syscall.h +0 -8
@@ -21,14 +21,6 @@ typedef long (*sys_call_ptr_t)(const struct pt_regs *);extern const sys_call_ptr_t sys_call_table[];/* -* These may not exist, but still put the prototypes in so we -* can use IS_ENABLED(). -*/ -extern long ia32_sys_call (const struct pt_regs *,unsigned int nr); -extern long x32_sys_call (const struct pt_regs *,unsigned int nr); -extern long x64_sys_call (const struct pt_regs *,unsigned int nr); - -/* * Only the low 32 bits of orig_ax are meaningful, so we return int. * This importantly ignores the high bits on 64-bit, so comparisons * sign-extend the low 32 bits.
Thomas Gleixner
maintainerPATCH 16/18 x86/entry: Get rid of the sys_ni_syscall() indirection
In reply to Thomas GleixnerInvoking sys_ni_syscall() from a code path, which already knows that the syscall number is invalid just to assign -ENOSYS to regs->ax is a pointless exercise. It's even redundant as the low level entry code already has set regs->ax to -ENOSYS on entry.
Remove the extra conditionals and the function calls.
--- arch/x86/entry/syscall_32.c | 2 -- arch/x86/entry/syscall_64.c | 10 +++------- 2 files changed, 3 insertions(+), 9 deletions(-)
arch/x86/entry/syscall_32.c +0 -2
@@ -81,8 +81,6 @@ static __always_inline void do_syscall_3if (likely (unr < IA32_NR_syscalls)) { unr =array_index_nospec (unr, IA32_NR_syscalls); regs->ax =ia32_sys_call (regs, unr); - }else if (nr !=-1 ) { - regs->ax =__ia32_sys_ni_syscall (regs); } }
arch/x86/entry/syscall_64.c +3 -7
@@ -68,7 +68,7 @@ static __always_inline bool do_syscall_xreturn false; } -static __always_inline bool do_syscall_x32(struct pt_regs *regs, int nr) +static __always_inline void do_syscall_x32(struct pt_regs *regs, int nr) {/* * Adjust the starting offset of the table, and convert numbers
@@ -80,9 +80,7 @@ static __always_inline bool do_syscall_xif (IS_ENABLED (CONFIG_X86_X32_ABI ) &&likely (xnr < X32_NR_syscalls)) { xnr =array_index_nospec (xnr, X32_NR_syscalls); regs->ax =x32_sys_call (regs, xnr); -return true; } -return false; }/* Returns true to return using SYSRET, or false to use IRET */
@@ -92,10 +90,8 @@ static __always_inline bool do_syscall_xinstrumentation_begin (); -if (!do_syscall_x64 (regs, nr) && !do_syscall_x32 (regs, nr) && nr !=-1 ) { -/* Invalid system call, but still a system call. */ - regs->ax =__x64_sys_ni_syscall (regs); - } +if (!do_syscall_x64 (regs, nr)) +do_syscall_x32 (regs, nr);instrumentation_end ();syscall_exit_to_user_mode (regs);
Re: [patch 16/18] x86/entry: Get rid of the sys_ni_syscall() indirection
Quoted 4 lines · Thomas Gleixner
Invoking
sys_ni_syscall()from a code path, which already knows that the syscall number is invalid just to assign-ENOSYStoregs->axis a pointless exercise. It's even redundant as the low level entry code already has setregs->axto-ENOSYSon entry.
Makes sense, the all reltaed entry has already initialized regs->ax to -ENOSYS.
This makes the code very concise.
LGTM
Quoted 55 lines
Remove the extra conditionals and the function calls.
Signed-off-by Thomas Gleixner <[email protected]>--- arch/x86/entry/syscall_32.c | 2 -- arch/x86/entry/syscall_64.c | 10 +++------- 2 files changed, 3 insertions(+), 9 deletions(-)arch/x86/entry/syscall_32.c +0
-2@@ -81,8 +81,6 @@ static __always_inline void do_syscall_3if (likely (unr < IA32_NR_syscalls)) { unr =array_index_nospec (unr, IA32_NR_syscalls); regs->ax =ia32_sys_call (regs, unr); - }else if (nr !=-1 ) { - regs->ax =__ia32_sys_ni_syscall (regs); } }arch/x86/entry/syscall_64.c +3
-7@@ -68,7 +68,7 @@ static __always_inline bool do_syscall_xreturn false; } -static __always_inline bool do_syscall_x32(struct pt_regs *regs, int nr) +static __always_inline void do_syscall_x32(struct pt_regs *regs, int nr) {/* * Adjust the starting offset of the table, and convert numbers @@ -80,9 +80,7 @@ static __always_inline bool do_syscall_xif (IS_ENABLED (CONFIG_X86_X32_ABI ) &&likely (xnr < X32_NR_syscalls)) { xnr =array_index_nospec (xnr, X32_NR_syscalls); regs->ax =x32_sys_call (regs, xnr); -return true; } -return false; }/* Returns true to return using SYSRET, or false to use IRET */ @@ -92,10 +90,8 @@ static __always_inline bool do_syscall_xinstrumentation_begin (); -if (!do_syscall_x64 (regs, nr) && !do_syscall_x32 (regs, nr) && nr !=-1 ) { -/* Invalid system call, but still a system call. */ - regs->ax =__x64_sys_ni_syscall (regs); - } +if (!do_syscall_x64 (regs, nr)) +do_syscall_x32 (regs, nr);instrumentation_end ();syscall_exit_to_user_mode (regs);
[tip: core/entry] x86/entry: Get rid of the sys_ni_syscall() indirection
In reply to Thomas GleixnerThe following commit has been merged into the core/entry branch of tip:
The following commit has been merged into the core/entry branch of tip:
Commit-ID: 1b1f3b3e1b3945ae6e49081fd3586a6833d4a555 Gitweb: https://git.kernel.org/tip/1b1f3b3e1b3945ae6e49081fd3586a6833d4a555 Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 07 Jul 2026 21:07:01 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Sun, 12 Jul 2026 12:38:02 +02:00
x86/entry: Get rid of the sys_ni_syscall() indirection
Invoking sys_ni_syscall() from a code path, which already knows that the syscall number is invalid just to assign -ENOSYS to regs->ax is a pointless exercise. It's even redundant as the low level entry code already has set regs->ax to -ENOSYS on entry.
Remove the extra conditionals and the function calls.
--- arch/x86/entry/syscall_32.c | 2 -- arch/x86/entry/syscall_64.c | 10 +++------- 2 files changed, 3 insertions(+), 9 deletions(-)
arch/x86/entry/syscall_32.c +0 -2
@@ -81,8 +81,6 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, int nr)if (likely (unr < IA32_NR_syscalls)) { unr =array_index_nospec (unr, IA32_NR_syscalls); regs->ax =ia32_sys_call (regs, unr); - }else if (nr !=-1 ) { - regs->ax =__ia32_sys_ni_syscall (regs); } }
arch/x86/entry/syscall_64.c +3 -7
@@ -68,7 +68,7 @@ static __always_inline bool do_syscall_x64(struct pt_regs *regs, int nr)return false; } -static __always_inline bool do_syscall_x32(struct pt_regs *regs, int nr) +static __always_inline void do_syscall_x32(struct pt_regs *regs, int nr) {/* * Adjust the starting offset of the table, and convert numbers
@@ -80,9 +80,7 @@ static __always_inline bool do_syscall_x32(struct pt_regs *regs, int nr)if (IS_ENABLED (CONFIG_X86_X32_ABI ) &&likely (xnr < X32_NR_syscalls)) { xnr =array_index_nospec (xnr, X32_NR_syscalls); regs->ax =x32_sys_call (regs, xnr); -return true; } -return false; }/* Returns true to return using SYSRET, or false to use IRET */
@@ -92,10 +90,8 @@ __visible noinstr bool do_syscall_64(struct pt_regs *regs, int nr)instrumentation_begin (); -if (!do_syscall_x64 (regs, nr) && !do_syscall_x32 (regs, nr) && nr !=-1 ) { -/* Invalid system call, but still a system call. */ - regs->ax =__x64_sys_ni_syscall (regs); - } +if (!do_syscall_x64 (regs, nr)) +do_syscall_x32 (regs, nr);instrumentation_end ();syscall_exit_to_user_mode (regs);
Re: [patch 16/18] x86/entry: Get rid of the sys_ni_syscall() indirection
In reply to Thomas GleixnerQuoted 6 lines · Thomas Gleixner
Invoking
sys_ni_syscall()from a code path, which already knows that the syscall number is invalid just to assign-ENOSYStoregs->axis a pointless exercise. It's even redundant as the low level entry code already has setregs->axto-ENOSYSon entry.Remove the extra conditionals and the function calls.
Since this patch, tools/testing/selftests/x86/syscall_numbering_64 throws in this:
|[RUN] Running tests under ptrace: modifying the default return |[RUN] Checking system calls with msb = 0 (0x0) |[RUN] Checking some common syscalls as 64 bit |[OK] x64 syscall 0:0 returned 0 as expected |[OK] x64 syscall 0:1 returned 0 as expected |[RUN] Checking some 64-bit only syscalls as 64 bit |[OK] x64 syscall 0:19 returned 0 as expected |[OK] x64 syscall 0:20 returned 0 as expected |[RUN] Checking out of range system calls |[FAIL] x32 syscall 0:-64 returned -9999, but it should have returned -ENOSYS … |[FAIL] x32 syscall 0:-2 returned -9999, but it should have returned -ENOSYS |[FAIL] x32 syscalls 0:-64..-2 had 63 failure |[OK] x32 syscall 0:-1 returned MODIFIED_BY_PTRACE as expected |[FAIL] x64 syscall 0:1073741760 returned -9999, but it should have returned -ENOSYS … |[FAIL] x64 syscall 0:1073741823 returned -9999, but it should have returned -ENOSYS |[FAIL] x64 syscalls 0:1073741760..1073741823 had 64 failure |[FAIL] x64 syscall 0:-64 returned -9999, but it should have returned -ENOSYS … |[FAIL] x64 syscall 0:547 returned -9999, but it should have returned -ENOSYS |[FAIL] x64 syscalls 0:512..547 had 36 failure |[RUN] Checking some common syscalls as x32 |[OK] x32 syscall 0:0 returned 0 as expected … |[RUN] Checking out of range system calls |[FAIL] x32 syscall 1:-64 returned -9999, but it should have returned -ENOSYS |[FAIL] x32 syscalls 1:-64..-2 had 63 failure |[OK] x32 syscall 1:-1 returned MODIFIED_BY_PTRACE as expected |[FAIL] x64 syscall 1:1073741760 returned -9999, but it should have returned -ENOSYS
…
and so on… The test has
| #define MODIFIED_BY_PTRACE -9999
and the ptracer modifies the return code. However not always. Not sure if this was indeed a pointless exercise or not.
The test could be updated via the hunk below in case the new behaviour is what is expected. hpa made the extension to the test in commit 795e2a023b808 ("selftests/x86/syscall: Add tests under ptrace to syscall_numbering_64").
tools/testing/selftests/x86/syscall_numbering.c +13 -8
@@ -250,6 +250,7 @@ static bool test_x32(void)static void test_syscalls_common (int msb) {enum ptrace_pass pass = sh->ptrace_pass; +int expected_ret = -ENOSYS ;run ("Checking some common syscalls as 64 bit\n" );check_zero (msb,SYS_READ );
@@ -260,18 +261,22 @@ static void test_syscalls_common(int msb)check_zero (msb,X64_WRITEV );run ("Checking out of range system calls\n" ); -check_for (msb,-64 ,-2 , -ENOSYS );if (pass >=PTP_FUZZRET ) -check_for (msb,-1 ,-1 ,MODIFIED_BY_PTRACE ); -else -check_for (msb,-1 ,-1 , -ENOSYS ); -check_for (msb,X32_BIT -64 ,X32_BIT -1 , -ENOSYS ); -check_for (msb,-64 -X32_BIT ,-1 -X32_BIT , -ENOSYS ); -check_for (msb,INT_MAX -64 ,INT_MAX -1 , -ENOSYS ); + expected_ret =MODIFIED_BY_PTRACE ; +check_for (msb,-64 ,-2 , expected_ret); +check_for (msb,-1 ,-1 , expected_ret); +check_for (msb,X32_BIT -64 ,X32_BIT -1 , expected_ret); +check_for (msb,-64 -X32_BIT ,-1 -X32_BIT , expected_ret); +check_for (msb,INT_MAX -64 ,INT_MAX -1 , expected_ret); }static void test_syscalls_with_x32 (int msb) { +enum ptrace_pass pass = sh->ptrace_pass; +int expected_ret = -ENOSYS ; + +if (pass >=PTP_FUZZRET ) + expected_ret =MODIFIED_BY_PTRACE ;/* * Syscalls 512-547 are "x32" syscalls. They are * intended to be called with the x32 (0x40000000) bit
@@ -279,7 +284,7 @@ static void test_syscalls_with_x32(int msb)* nonsense and should not work. */ run ("Checking x32 syscalls as 64 bit\n" ); -check_for (msb,512 ,547 , -ENOSYS ); +check_for (msb,512 ,547 , expected_ret);run ("Checking some common syscalls as x32\n" );check_zero (msb,SYS_READ |X32_BIT );
Sebastian
Re: [patch 16/18] x86/entry: Get rid of the sys_ni_syscall() indirection
tools/testing/selftests/x86/syscall_numbering.c
Quoted 9 lines · To Thomas Gleixner
The test could be updated via the hunk below in case the new behaviour is what is expected. hpa made the extension to the test in commit
795e2a023b808("selftests/x86/syscall: Add tests under ptrace tosyscall_numbering_64").tools/testing/selftests/x86/syscall_numbering.c +0
-0
Now I notice the fix depends on CONFIG_X86_X32_ABI=y (fails for =n). But we want to get rid of it anyway so… CONFIG_IA32_EMULATION is not affected (with the fix).
Sebastian
H. Peter Anvin
reviewerRe: [patch 16/18] x86/entry: Get rid of the sys_ni_syscall() indirection
Quoted 6 lines · Sebastian Andrzej Siewior
Quoted 5 lines · To Thomas Gleixner
The test could be updated via the hunk below in case the new behaviour is what is expected. hpa made the extension to the test in commit
795e2a023b808("selftests/x86/syscall: Add tests under ptrace tosyscall_numbering_64").
Quoted 9 lines
tools/testing/selftests/x86/syscall_numbering.c
Quoted 4 lines
tools/testing/selftests/x86/syscall_numbering.c +0
-0Now I notice the fix depends on
CONFIG_X86_X32_ABI=y(fails for =n). But we want to get rid of it anyway so…CONFIG_IA32_EMULATIONis not affected (with the fix).
It would be very simple to probe for by issuing a simple system call like getppid() with the x32 bit set.
-hpa
_______________________________________________
linux-snps-arc mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-snps-arc
Thomas Gleixner
maintainerRe: [patch 16/18] x86/entry: Get rid of the sys_ni_syscall() indirection
In reply to Sebastian Andrzej SiewiorQuoted 40 lines · Sebastian Andrzej Siewior
Quoted 6 lines · Thomas Gleixner
Invoking
sys_ni_syscall()from a code path, which already knows that the syscall number is invalid just to assign-ENOSYStoregs->axis a pointless exercise. It's even redundant as the low level entry code already has setregs->axto-ENOSYSon entry.Remove the extra conditionals and the function calls.
Since this patch,
tools/testing/selftests/x86/syscall_numbering_64throws in this:|[RUN] Running tests under ptrace: modifying the default return |[RUN] Checking system calls with msb = 0 (0x0) |[RUN] Checking some common syscalls as 64 bit |[OK] x64 syscall 0:0 returned 0 as expected |[OK] x64 syscall 0:1 returned 0 as expected |[RUN] Checking some 64-bit only syscalls as 64 bit |[OK] x64 syscall 0:19 returned 0 as expected |[OK] x64 syscall 0:20 returned 0 as expected |[RUN] Checking out of range system calls |[FAIL] x32 syscall 0:-64 returned -9999, but it should have returned -ENOSYS … |[FAIL] x32 syscall 0:-2 returned -9999, but it should have returned -ENOSYS |[FAIL] x32 syscalls 0:-64..-2 had 63 failure |[OK] x32 syscall 0:-1 returned MODIFIED_BY_PTRACE as expected |[FAIL] x64 syscall 0:1073741760 returned -9999, but it should have returned -ENOSYS … |[FAIL] x64 syscall 0:1073741823 returned -9999, but it should have returned -ENOSYS |[FAIL] x64 syscalls 0:1073741760..1073741823 had 64 failure |[FAIL] x64 syscall 0:-64 returned -9999, but it should have returned -ENOSYS … |[FAIL] x64 syscall 0:547 returned -9999, but it should have returned -ENOSYS |[FAIL] x64 syscalls 0:512..547 had 36 failure |[RUN] Checking some common syscalls as x32 |[OK] x32 syscall 0:0 returned 0 as expected … |[RUN] Checking out of range system calls |[FAIL] x32 syscall 1:-64 returned -9999, but it should have returned -ENOSYS |[FAIL] x32 syscalls 1:-64..-2 had 63 failure |[OK] x32 syscall 1:-1 returned MODIFIED_BY_PTRACE as expected |[FAIL] x64 syscall 1:1073741760 returned -9999, but it should have returned -ENOSYS
Quoted 8 lines
…
and so on… The test has
| #define
MODIFIED_BY_PTRACE-9999and the ptracer modifies the return code. However not always. Not sure if this was indeed a pointless exercise or not.
Hrmm. That's weird. Let me have a look.
Thomas Gleixner
maintainerRe: [patch 16/18] x86/entry: Get rid of the sys_ni_syscall() indirection
Quoted 9 lines · Thomas Gleixner
Quoted 8 lines · Sebastian Andrzej Siewior
On 2026-07-07 21:07:01 [+0200], Thomas Gleixner wrote:
|[RUN] Checking out of range system calls |[FAIL] x32 syscall 1:-64 returned -9999, but it should have returned -ENOSYS |[FAIL] x32 syscalls 1:-64..-2 had 63 failure |[OK] x32 syscall 1:-1 returned MODIFIED_BY_PTRACE as expected |[FAIL] x64 syscall 1:1073741760 returned -9999, but it should have returned -ENOSYS…
Quoted 8 lines
Quoted 6 lines
and so on… The test has
| #define
MODIFIED_BY_PTRACE-9999and the ptracer modifies the return code. However not always. Not sure if this was indeed a pointless exercise or not.
Hrmm. That's weird. Let me have a look.
So I clearly failed to decode the overloading of the -1L return value correctly and then failed to run the stupid test.
TBH, this whole thing was a horrid and inconsistent mess.
The logic in the original code was:
When the entry work code returned an invalid syscall number then the
return value in regs->ax was set to -ENOSYS, except when the
returned syscall number was -1. Syscall number "-1" indicated that
the syscall has to be aborted.
regs->ax = -ENOSYS;
syscall = enter_work(regs, syscall);
if (syscall_in_range(syscall))
regs->ax = do_syscall(syscall);
else if (syscall != -1)
regs->ax = -ENOSYS;So if the ptrace check in enter_work() overwrote regs->ax and the syscall number (either as supplied by user space or rewritten) was out of range and not -1 then the x86 entry code overwrote regs->ax to -ENOSYS again. IOW, there is no distinction between a check induced abort and a syscall with syscall number -1.
The rework changed the return value to boolean, which is true when the syscall should be invoked and false when one of the checks requests to abort the syscall. In that case the return code does not touch the return value in regs->ax.
If the eventually modified syscall number is out of range then the code relies on the fact that regs->ax was preset with -ENOSYS, i.e.:
regs->ax = -ENOSYS;
// True indicates to proceed
if (enter_work(regs, &syscall)) {
if (syscall_in_range(syscall))
regs->ax = do_syscall(syscall);
}That seems to be equivalent, but it is not when ptrace() modifies the return value in regs->ax and also rewrites the syscall number to an invalid value or leaves the user supplied invalid value intact and does _NOT_ abort the syscall.
So the reworked code does not overwrite the tracer modified return value with -ENOSYS in that case and returns whatever the tracer decided to put into it.
TBH, that makes a lot more sense than the original behavior. If the tracer decides to fiddle with the default return value then that's what the tracer intended.
That makes the behavior consistent vs. other abort scenarios:
ptrace()
regs->ax = MAGIC;
return true; // Allow syscall
seccomp()
return false; // Abort syscall
So when the tracer modified the return value and seccomp aborts the syscall then the tracer induced value is preserved. That was the case in the original code as well because seccomp() indicated the abort by returning -1 as the modified syscall number. Similar effects when ftrace (BPF, kprobe) decided to overwrite the syscall number).
Bringing the original behaviour back is trivial enough, but I'm not convinced that it makes any sense and is worth it. At least this confines the x32 specific insanity of treating -1 special to x32...
Thanks,
tglx
---
arch/x86/entry/syscall_32.c +2 -0
@@ -77,6 +77,8 @@ static __always_inline void do_syscall_3if (likely (nr < IA32_NR_syscalls)) { nr =array_index_nospec (nr, IA32_NR_syscalls); regs->ax =ia32_sys_call (regs, (unsigned int )nr); + }else { + regs->ax = -ENOSYS ; } }
arch/x86/entry/syscall_64.c +15 -4
@@ -64,15 +64,24 @@ static __always_inline bool do_syscall_xreturn false; } -static __always_inline void do_syscall_x32(struct pt_regs *regs, unsigned long nr) +static __always_inline bool do_syscall_x32(struct pt_regs *regs, unsigned long nr) { +if (!IS_ENABLED (CONFIG_X86_X32_ABI )) +return false; + +/* Preserve the historic insanity of treating -1 special on x32 */ +if (nr ==ULONG_MAX ) +return true; +/* Adjust the starting offset of the table */ nr -= __X32_SYSCALL_BIT; -if (IS_ENABLED (CONFIG_X86_X32_ABI ) &&likely (nr < X32_NR_syscalls)) { +if (likely (nr < X32_NR_syscalls)) { nr =array_index_nospec (nr, X32_NR_syscalls); regs->ax =x32_sys_call (regs, (unsigned int )nr); +return true; } +return false; }/* Returns true to return using SYSRET, or false to use IRET */
@@ -81,8 +90,10 @@ static __always_inline void do_syscall_xif (likely (syscall_enter_from_user_mode_randomize_stack (regs, &nr))) {instrumentation_begin (); -if (!do_syscall_x64 (regs, nr)) -do_syscall_x32 (regs, nr); +if (unlikely (!do_syscall_x64 (regs, nr))) { +if (!do_syscall_x32 (regs, nr)) + regs->ax = -ENOSYS ; + }instrumentation_end (); }
H. Peter Anvin
reviewerRe: [patch 16/18] x86/entry: Get rid of the sys_ni_syscall() indirection
Quoted 149 lines · Thomas Gleixner
Quoted 9 lines · Thomas Gleixner
Quoted 8 lines · Sebastian Andrzej Siewior
On 2026-07-07 21:07:01 [+0200], Thomas Gleixner wrote:
|[RUN] Checking out of range system calls |[FAIL] x32 syscall 1:-64 returned -9999, but it should have returned -ENOSYS |[FAIL] x32 syscalls 1:-64..-2 had 63 failure |[OK] x32 syscall 1:-1 returned MODIFIED_BY_PTRACE as expected |[FAIL] x64 syscall 1:1073741760 returned -9999, but it should have returned -ENOSYS…
Quoted 8 lines
Quoted 6 lines
and so on… The test has
| #define
MODIFIED_BY_PTRACE-9999and the ptracer modifies the return code. However not always. Not sure if this was indeed a pointless exercise or not.
Hrmm. That's weird. Let me have a look.
So I clearly failed to decode the overloading of the -1L return value correctly and then failed to run the stupid test.
TBH, this whole thing was a horrid and inconsistent mess.
The logic in the original code was:
When the entry work code returned an invalid syscall number then the return value in regs->ax was set to -ENOSYS, except when the returned syscall number was -1. Syscall number "-1" indicated that the syscall has to be aborted. regs->ax = -ENOSYS; syscall = enter_work(regs, syscall); if (syscall_in_range(syscall)) regs->ax = do_syscall(syscall); else if (syscall != -1) regs->ax = -ENOSYS;So if the ptrace check in
enter_work()overwroteregs->axand the syscall number (either as supplied by user space or rewritten) was out of range and not -1 then the x86 entry code overwroteregs->axto-ENOSYSagain. IOW, there is no distinction between a check induced abort and a syscall with syscall number -1.The rework changed the return value to boolean, which is true when the syscall should be invoked and false when one of the checks requests to abort the syscall. In that case the return code does not touch the return value in
regs->ax.If the eventually modified syscall number is out of range then the code relies on the fact that
regs->axwas preset with-ENOSYS, i.e.:regs->ax = -ENOSYS; // True indicates to proceed if (enter_work(regs, &syscall)) { if (syscall_in_range(syscall)) regs->ax = do_syscall(syscall); }That seems to be equivalent, but it is not when
ptrace()modifies the return value inregs->axand also rewrites the syscall number to an invalid value or leaves the user supplied invalid value intact and does _NOT_ abort the syscall.So the reworked code does not overwrite the tracer modified return value with
-ENOSYSin that case and returns whatever the tracer decided to put into it.TBH, that makes a lot more sense than the original behavior. If the tracer decides to fiddle with the default return value then that's what the tracer intended.
That makes the behavior consistent vs. other abort scenarios:
ptrace() regs->ax = MAGIC; return true; // Allow syscall
seccomp()
return false; // Abort syscallSo when the tracer modified the return value and seccomp aborts the syscall then the tracer induced value is preserved. That was the case in the original code as well because
seccomp()indicated the abort by returning -1 as the modified syscall number. Similar effects when ftrace (BPF, kprobe) decided to overwrite the syscall number).Bringing the original behaviour back is trivial enough, but I'm not convinced that it makes any sense and is worth it. At least this confines the x32 specific insanity of treating -1 special to x32...
Thanks,
tglx
---arch/x86/entry/syscall_32.c +2
-0@@ -77,6 +77,8 @@ static __always_inline void do_syscall_3if (likely (nr < IA32_NR_syscalls)) { nr =array_index_nospec (nr, IA32_NR_syscalls); regs->ax =ia32_sys_call (regs, (unsigned int )nr); + }else { + regs->ax = -ENOSYS ; } }arch/x86/entry/syscall_64.c +11
-2@@ -64,15 +64,24 @@ static __always_inline bool do_syscall_xreturn false; } -static __always_inline void do_syscall_x32(struct pt_regs *regs, unsigned long nr) +static __always_inline bool do_syscall_x32(struct pt_regs *regs, unsigned long nr) { +if (!IS_ENABLED (CONFIG_X86_X32_ABI )) +return false; + +/* Preserve the historic insanity of treating -1 special on x32 */ +if (nr ==ULONG_MAX ) +return true; +/* Adjust the starting offset of the table */ nr -= __X32_SYSCALL_BIT; -if (IS_ENABLED (CONFIG_X86_X32_ABI ) &&likely (nr < X32_NR_syscalls)) { +if (likely (nr < X32_NR_syscalls)) { nr =array_index_nospec (nr, X32_NR_syscalls); regs->ax =x32_sys_call (regs, (unsigned int )nr); +return true; } +return false; }/* Returns true to return using SYSRET, or false to use IRET */ @@ -81,8 +90,10 @@ static __always_inline void do_syscall_xif (likely (syscall_enter_from_user_mode_randomize_stack (regs, &nr))) {instrumentation_begin ();
arch/x86/entry/syscall_64.c static __always_inline void do_syscall_x · line 99
Quoted 10 lines
arch/x86/entry/syscall_64.c +4
-2-if (!do_syscall_x64 (regs, nr)) -do_syscall_x32 (regs, nr); +if (unlikely (!do_syscall_x64 (regs, nr))) { +if (!do_syscall_x32 (regs, nr)) + regs->ax = -ENOSYS ; + }instrumentation_end (); }
It was never limited to x32...
Thomas Gleixner
maintainerRe: [patch 16/18] x86/entry: Get rid of the sys_ni_syscall() indirection
Quoted 12 lines · H. Peter Anvin
arch/x86/entry/syscall_64.c static __always_inline bool do_syscall_x · line 74
Quoted 9 lines · Thomas Gleixner
arch/x86/entry/syscall_64.c +1
-1-static __always_inline void do_syscall_x32(struct pt_regs *regs, unsigned long nr) +static __always_inline bool do_syscall_x32(struct pt_regs *regs, unsigned long nr){
arch/x86/entry/syscall_64.c +6
-0+if (!IS_ENABLED (CONFIG_X86_X32_ABI )) +return false; + +/* Preserve the historic insanity of treating -1 special on x32 */ +if (nr ==ULONG_MAX ) +return true;It was never limited to x32...
Tired brain misread the test output:
[RUN] Running tests under ptrace: modifying the default return
[RUN] Checking system calls with msb = 0 (0x0)
[OK] x32 syscalls 0:-64..-2 returned -ENOSYS as expected [OK] x32 syscall 0:-1 returned MODIFIED_BY_PTRACE as expected [OK] x64 syscalls 0:-64..-1 returned -ENOSYS as expected
But that's because the "-1" on x32 is actually 0xFFFFFFFF while on x64 it's 0x7FFFFFFF.
The whole mess comes from using -1 as indicator for syscall abort which is undistinguishable from a syscall(nr=-1).
Bah. Let me restore this nonsense.
Thanks,
tglx
Thomas Gleixner
maintainerRe: [patch 16/18] x86/entry: Get rid of the sys_ni_syscall() indirection
Quoted 9 lines · Thomas Gleixner
On Thu, Oct 22 2026 at 17:22, H. Peter Anvin wrote:
Tired brain misread the test output:[RUN] Running tests under ptrace: modifying the default return
[RUN] Checking system calls with msb = 0 (0x0)[OK] x32 syscalls 0:-64..-2 returned -ENOSYS as expected [OK] x32 syscall 0:-1 returned MODIFIED_BY_PTRACE as expected [OK] x64 syscalls 0:-64..-1 returned -ENOSYS as expected
Quoted 7 lines
But that's because the "-1" on x32 is actually
0xFFFFFFFFwhile on x64 it's0x7FFFFFFF.The whole mess comes from using -1 as indicator for syscall abort which is undistinguishable from a syscall(nr=-1).
Bah. Let me restore this nonsense.
The real question is how we ended up there. By design or as an implementation detail which got later set in stone and the selftest was written to test the implementation instead of testing against a specification.
I went back in history and in 2.6.12 the behavior was for both i386 and x86_64:
regs->ax = -ENOSYS; syscall_trace_enter(); if (syscall_nr < MAX) do_syscall(); ....
IOW, a tracer modification of regs->ax is not overwritten when the syscall number is out of range.
Between 2.6.19-rc2 and -rc3 x86_64 was changed to _always_ overwrite regs->ax when the syscall number is out of range.
In the 3.8 merge window seccomp introduced the -1 == skip bogosity which got fixed up and made "consistent" in several changes afterwards. Just that it never reached a state of consistency due to the overloading.
So are we stuck with this behavior or do we sit down and define what the correct behavior should be?
Thanks,
tglx
H. Peter Anvin
reviewerRe: [patch 16/18] x86/entry: Get rid of the sys_ni_syscall() indirection
Quoted 42 lines · Thomas Gleixner
Quoted 9 lines · Thomas Gleixner
On Thu, Oct 22 2026 at 17:22, H. Peter Anvin wrote:
Tired brain misread the test output:[RUN] Running tests under ptrace: modifying the default return
[RUN] Checking system calls with msb = 0 (0x0)[OK] x32 syscalls 0:-64..-2 returned -ENOSYS as expected [OK] x32 syscall 0:-1 returned MODIFIED_BY_PTRACE as expected [OK] x64 syscalls 0:-64..-1 returned -ENOSYS as expectedQuoted 7 lines
But that's because the "-1" on x32 is actually
0xFFFFFFFFwhile on x64 it's0x7FFFFFFF.The whole mess comes from using -1 as indicator for syscall abort which is undistinguishable from a syscall(nr=-1).
Bah. Let me restore this nonsense.
The real question is how we ended up there. By design or as an implementation detail which got later set in stone and the selftest was written to test the implementation instead of testing against a specification.
I went back in history and in 2.6.12 the behavior was for both i386 and
x86_64:
regs->ax=-ENOSYS;
syscall_trace_enter();
if (syscall_nr< MAX)
do_syscall();
....IOW, a tracer modification of
regs->axis not overwritten when the syscall number is out of range.Between 2.6.19-rc2 and -rc3
x86_64was changed to _always_ overwriteregs->axwhen the syscall number is out of range.In the 3.8 merge window seccomp introduced the -1 == skip bogosity which got fixed up and made "consistent" in several changes afterwards. Just that it never reached a state of consistency due to the overloading.
Quoted 8 lines
So are we stuck with this behavior or do we sit down and define what the correct behavior should be?
Thanks,
tglx
Going back on something from 3.8 that is actively used seems unwise. I fear that that ship sailed a long time ago, even though I hate it just as much as you do.
Thomas Gleixner
maintainerRe: [patch 16/18] x86/entry: Get rid of the sys_ni_syscall() indirection
Quoted 25 lines · H. Peter Anvin
Quoted 24 lines · Thomas Gleixner
The real question is how we ended up there. By design or as an implementation detail which got later set in stone and the selftest was written to test the implementation instead of testing against a specification.
I went back in history and in 2.6.12 the behavior was for both i386 and
x86_64:
regs->ax=-ENOSYS;
syscall_trace_enter();
if (syscall_nr< MAX)
do_syscall();
....IOW, a tracer modification of
regs->axis not overwritten when the syscall number is out of range.Between 2.6.19-rc2 and -rc3
x86_64was changed to _always_ overwriteregs->axwhen the syscall number is out of range.In the 3.8 merge window seccomp introduced the -1 == skip bogosity which got fixed up and made "consistent" in several changes afterwards. Just that it never reached a state of consistency due to the overloading.
Quoted 7 lines
Quoted 3 lines
So are we stuck with this behavior or do we sit down and define what the correct behavior should be?
Going back on something from 3.8 that is actively used seems unwise. I fear that that ship sailed a long time ago, even though I hate it just as much as you do.
Well, overwriting the tracer written value for invalid syscall numbers is something we can't undo. Though the interesting question is whether the -1 overloading needs to be preserved. The new code uses returns false when the syscall has to be aborted and that leaves the return code untouched. When syscall_enter_trace() returns true, the syscall is invoked, so it would be consistent to overwrite the return code with -ENOSYS even for -1. But yeah, some esoteric nonsense might rely on that behaviour for the wrong reasons.
Fix below.
Thanks,
tglx
---
arch/x86/entry/syscall_32.c +2 -0
@@ -77,6 +77,8 @@ static __always_inline void do_syscall_3if (likely (nr < IA32_NR_syscalls)) { nr =array_index_nospec (nr, IA32_NR_syscalls); regs->ax =ia32_sys_call (regs, (unsigned int )nr); + }else { + regs->ax = -ENOSYS ; } }
arch/x86/entry/syscall_64.c +22 -4
@@ -64,15 +64,20 @@ static __always_inline bool do_syscall_xreturn false; } -static __always_inline void do_syscall_x32(struct pt_regs *regs, unsigned long nr) +static __always_inline bool do_syscall_x32(struct pt_regs *regs, unsigned long nr) { +if (!IS_ENABLED (CONFIG_X86_X32_ABI )) +return false; +/* Adjust the starting offset of the table */ nr -= __X32_SYSCALL_BIT; -if (IS_ENABLED (CONFIG_X86_X32_ABI ) &&likely (nr < X32_NR_syscalls)) { +if (likely (nr < X32_NR_syscalls)) { nr =array_index_nospec (nr, X32_NR_syscalls); regs->ax =x32_sys_call (regs, (unsigned int )nr); +return true; } +return false; }/* Returns true to return using SYSRET, or false to use IRET */
@@ -81,8 +86,21 @@ static __always_inline void do_syscall_xif (likely (syscall_enter_from_user_mode_randomize_stack (regs, &nr))) {instrumentation_begin (); -if (!do_syscall_x64 (regs, nr)) -do_syscall_x32 (regs, nr); +if (unlikely (!do_syscall_x64 (regs, nr))) { +/* +* The special treatment of syscall number -1 is a +* historical bogosity as the original code used -1 to +* indicate syscall abort, which is not distinguishable +* from a syscall which is invoked with syscall number +* -1. The historic behavior is to keep the return value +* in regs->ax unmodified in that case, which means it's +* either the preset value -ENOSYS or a value which was +* written by a tracer. If the syscall number is invalid +* but not -1 then overwrite any tracer modification. +*/ +if (!do_syscall_x32 (regs, nr) && nr !=-1L ) + regs->ax = -ENOSYS ; + }instrumentation_end (); }
Thomas Gleixner
maintainerPATCH 1/1 x86/entry: Fix ptrace regression
The recent rework of the syscall entry code missed the historical detail of the abuse of syscall number -1L to abort a syscall and keep modifications by tracers to the return value, while a rewrite of the syscall number to an invalid value undoes eventual tracer modification to the return value and overwrites it with -ENOSYS.
Restore the original behaviour.
--- arch/x86/entry/syscall_32.c | 2 ++ arch/x86/entry/syscall_64.c | 26 ++++++++++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-)
arch/x86/entry/syscall_32.c +2 -0
@@ -77,6 +77,8 @@ static __always_inline void do_syscall_3if (likely (nr < IA32_NR_syscalls)) { nr =array_index_nospec (nr, IA32_NR_syscalls); regs->ax =ia32_sys_call (regs, (unsigned int )nr); + }else { + regs->ax = -ENOSYS ; } }
arch/x86/entry/syscall_64.c +22 -4
@@ -64,15 +64,20 @@ static __always_inline bool do_syscall_xreturn false; } -static __always_inline void do_syscall_x32(struct pt_regs *regs, unsigned long nr) +static __always_inline bool do_syscall_x32(struct pt_regs *regs, unsigned long nr) { +if (!IS_ENABLED (CONFIG_X86_X32_ABI )) +return false; +/* Adjust the starting offset of the table */ nr -= __X32_SYSCALL_BIT; -if (IS_ENABLED (CONFIG_X86_X32_ABI ) &&likely (nr < X32_NR_syscalls)) { +if (likely (nr < X32_NR_syscalls)) { nr =array_index_nospec (nr, X32_NR_syscalls); regs->ax =x32_sys_call (regs, (unsigned int )nr); +return true; } +return false; }/* Returns true to return using SYSRET, or false to use IRET */
@@ -81,8 +86,21 @@ static __always_inline void do_syscall_xif (likely (syscall_enter_from_user_mode_randomize_stack (regs, &nr))) {instrumentation_begin (); -if (!do_syscall_x64 (regs, nr)) -do_syscall_x32 (regs, nr); +if (unlikely (!do_syscall_x64 (regs, nr))) { +/* +* The special treatment of syscall number -1 is a +* historical bogosity as the original code used -1 to +* indicate syscall abort, which is not distinguishable +* from a syscall which is invoked with syscall number +* -1. The historic behavior is to keep the return value +* in regs->ax unmodified in that case, which means it's +* either the preset value -ENOSYS or a value which was +* written by a tracer. If the syscall number is invalid +* but not -1 then overwrite any tracer modification. +*/ +if (!do_syscall_x32 (regs, nr) && nr !=-1L ) + regs->ax = -ENOSYS ; + }instrumentation_end (); }
[email protected]
AI reviewRe: [PATCH] x86/entry: Fix ptrace regression
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] x86/entry: missing nr != -1L check in do_syscall_32_irqs_on() --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] x86/entry: missing nr != -1L check in do_syscall_32_irqs_on()
--
commit 99103a6b0e601cd2293cec25712d5b3e23db9efc
Author: Thomas Gleixner <[email protected]>
x86/entry: Fix ptrace regression
This commit restores the historical syscall entry behavior of preserving tracer modifications to regs->ax when a syscall is aborted with -1L while overwriting regs->ax with -ENOSYS when the syscall number is rewritten to an invalid value.
arch/x86/entry/syscall_32.c static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, unsigned · line 83
Quoted 12 lines
arch/x86/entry/syscall_32.c +2
-0@@ -77,6 +77,8 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, unsignedif (likely (nr < IA32_NR_syscalls)) { nr =array_index_nospec (nr, IA32_NR_syscalls); regs->ax =ia32_sys_call (regs, (unsigned int )nr); + }else { + regs->ax = -ENOSYS ; } }
[Severity: High]
Should the else branch in do_syscall_32_irqs_on() in arch/x86/entry/syscall_32.c also check that nr != -1L before setting regs->ax = -ENOSYS, matching the check added to do_syscall_64() in arch/x86/entry/syscall_64.c and the logic prior to commit 1b1f3b3e1b39 ("x86/entry: Get rid of the sys_ni_syscall() indirection")?
When a 32-bit syscall (entered via do_int80_emulation(), fred_int80_emulation(), do_int80_syscall_32(), or __do_fast_syscall_32()) is traced with PTRACE_SYSCALL without SYSCALL_WORK_SYSCALL_EMU, syscall_enter_from_user_mode_work() runs:
include/linux/entry-common.h:syscall_enter_from_user_mode_work() {
...
if (unlikely(!syscall_trace_enter(regs, work, *syscall)))
return false;
/* Reread the syscall number as it might have been modified */
*syscall = syscall_get_nr(current, regs);
return true;
}If the tracer aborts the syscall at the syscall-entry stop by setting orig_ax to -1 and writing a return value into regs->ax, syscall_trace_enter() -> arch_ptrace_report_syscall_permit_entry() -> ptrace_report_syscall_permit_entry() returns true (unless a fatal signal is pending). syscall_enter_from_user_mode_work() then updates *syscall to -1L and returns true.
The caller then passes nr == (unsigned long)-1L into do_syscall_32_irqs_on(), where nr < IA32_NR_syscalls is false and the unconditional else branch overwrites the tracer-supplied regs->ax value with -ENOSYS.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/87mrrvxaty.ffs@fw13?part=1
Thomas Gleixner
maintainerPATCH v2 1/1 x86/entry: Fix ptrace regression
In reply to Thomas GleixnerThe recent rework of the syscall entry code missed the historical detail of the abuse of syscall number -1L to abort a syscall and keep modifications by tracers to the return value, while a rewrite of the syscall number to an invalid value undoes eventual tracer modification to the return value and overwrite it with -ENOSYS.
Restore the original behaviour.
---
V2: Add the missing -1 check in the 32bit path - sashiko
--- arch/x86/entry/syscall_32.c | 4 ++++ arch/x86/entry/syscall_64.c | 26 ++++++++++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-)
arch/x86/entry/syscall_32.c +4 -0
@@ -77,6 +77,10 @@ static __always_inline void do_syscall_3if (likely (nr < IA32_NR_syscalls)) { nr =array_index_nospec (nr, IA32_NR_syscalls); regs->ax =ia32_sys_call (regs, (unsigned int )nr); + }else { +/* See comment in do_syscall_64() */ +if (nr !=-1UL ) { + regs->ax = -ENOSYS ; } }
arch/x86/entry/syscall_64.c +22 -4
@@ -64,15 +64,20 @@ static __always_inline bool do_syscall_xreturn false; } -static __always_inline void do_syscall_x32(struct pt_regs *regs, unsigned long nr) +static __always_inline bool do_syscall_x32(struct pt_regs *regs, unsigned long nr) { +if (!IS_ENABLED (CONFIG_X86_X32_ABI )) +return false; +/* Adjust the starting offset of the table */ nr -= __X32_SYSCALL_BIT; -if (IS_ENABLED (CONFIG_X86_X32_ABI ) &&likely (nr < X32_NR_syscalls)) { +if (likely (nr < X32_NR_syscalls)) { nr =array_index_nospec (nr, X32_NR_syscalls); regs->ax =x32_sys_call (regs, (unsigned int )nr); +return true; } +return false; }/* Returns true to return using SYSRET, or false to use IRET */
@@ -81,8 +86,21 @@ static __always_inline void do_syscall_xif (likely (syscall_enter_from_user_mode_randomize_stack (regs, &nr))) {instrumentation_begin (); -if (!do_syscall_x64 (regs, nr)) -do_syscall_x32 (regs, nr); +if (unlikely (!do_syscall_x64 (regs, nr))) { +/* +* The special treatment of syscall number -1 is a +* historical bogosity as the original code used -1 to +* indicate syscall abort, which is not distinguishable +* from a syscall which is invoked with syscall number +* -1. The historic behavior is to keep the return value +* in regs->ax unmodified in that case, which means it's +* either the preset value -ENOSYS or a value which was +* written by a tracer. If the syscall number is invalid +* but not -1 then overwrite any tracer modification. +*/ +if (!do_syscall_x32 (regs, nr) && nr !=-1L ) + regs->ax = -ENOSYS ; + }instrumentation_end (); }
[email protected]
AI reviewRe: [PATCH V2] x86/entry: Fix ptrace regression
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] x86/entry: unmatched opening brace in do_syscall_32_irqs_on() breaks build --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] x86/entry: unmatched opening brace in do_syscall_32_irqs_on() breaks build --
commit b8945a5f45d9b3a8ab21f8b9c553fa0b34f2a69f
Author: Thomas Gleixner <[email protected]>
x86/entry: Fix ptrace regression
This commit restores the historic syscall entry behavior where syscall number -1L keeps tracer modifications to regs->ax while other invalid syscall numbers overwrite regs->ax with -ENOSYS.
Quoted 5 lines
arch/x86/entry/syscall_32.c +0
-0
arch/x86/entry/syscall_32.c static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, unsigned · line 85
Quoted 9 lines
arch/x86/entry/syscall_32.c +4
-0@@ -77,6 +77,10 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, unsignedif (likely (nr < IA32_NR_syscalls)) { nr =array_index_nospec (nr, IA32_NR_syscalls); regs->ax =ia32_sys_call (regs, (unsigned int )nr); + }else { +/* See comment in do_syscall_64() */ +if (nr !=-1UL ) { + regs->ax = -ENOSYS ; } }
[Severity: High]
Does the inner if (nr != -1UL) statement in do_syscall_32_irqs_on() have an unmatched opening brace that leaves the function unclosed and breaks the build when CONFIG_X86_32 or CONFIG_IA32_EMULATION is enabled?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/87ecd4xwlr.ffs@fw13?part=1
Thomas Gleixner
maintainerRe: [PATCH V2] x86/entry: Fix ptrace regression
Quoted 4 lines · On Sun, Nov 01 2026 at 18:07, [email protected] wrote:
[Severity: High]
Does the inner if (nr != -1UL) statement indo_syscall_32_irqs_on()have an unmatched opening brace that leaves the function unclosed and breaks the build whenCONFIG_X86_32orCONFIG_IA32_EMULATIONis enabled?
Duh. Yes.
Re: [PATCH V2] x86/entry: Fix ptrace regression
In reply to Thomas Gleixnerarch/x86/entry/syscall_32.c static __always_inline void do_syscall_3 · line 83
Quoted 10 lines · Thomas Gleixner
arch/x86/entry/syscall_32.c +4
-0@@ -77,6 +77,10 @@ static __always_inline void do_syscall_3if (likely (nr < IA32_NR_syscalls)) { nr =array_index_nospec (nr, IA32_NR_syscalls); regs->ax =ia32_sys_call (regs, (unsigned int )nr); + }else { +/* See comment in do_syscall_64() */ +if (nr !=-1UL ) { + regs->ax = -ENOSYS ;
A curly closing bracket here and then it compiles for me. Or remove the one in the "if" line.
arch/x86/entry/syscall_32.c static __always_inline void do_syscall_3 · line 85
Quoted 2 lines
arch/x86/entry/syscall_32.c +0
-0} }
With either of the suggested changes:
Sebastian
[tip: x86/urgent] x86/entry: Fix ptrace regression
In reply to Thomas GleixnerThe following commit has been merged into the x86/urgent branch of tip:
The following commit has been merged into the x86/urgent branch of tip:
Commit-ID: b697faab2c92653ee13bd950c8de13551a78971d Gitweb: https://git.kernel.org/tip/b697faab2c92653ee13bd950c8de13551a78971d Author: Thomas Gleixner <[email protected]> AuthorDate: Sun, 01 Nov 2026 18:58:08 +01:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Tue, 03 Nov 2026 21:29:35 +01:00
x86/entry: Fix ptrace regression
The recent rework of the syscall entry code missed the historical detail of the abuse of syscall number -1L to abort a syscall and keep modifications by tracers to the return value, while a rewrite of the syscall number to an invalid value undoes eventual tracer modification to the return value and overwrite it with -ENOSYS.
Restore the original behaviour.
--- arch/x86/entry/syscall_32.c | 4 ++++ arch/x86/entry/syscall_64.c | 26 ++++++++++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-)
arch/x86/entry/syscall_32.c +4 -0
@@ -77,6 +77,10 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, unsignedif (likely (nr < IA32_NR_syscalls)) { nr =array_index_nospec (nr, IA32_NR_syscalls); regs->ax =ia32_sys_call (regs, (unsigned int )nr); + }else { +/* See comment in do_syscall_64() */ +if (nr !=-1UL ) + regs->ax = -ENOSYS ; } }
arch/x86/entry/syscall_64.c +22 -4
@@ -64,15 +64,20 @@ static __always_inline bool do_syscall_x64(struct pt_regs *regs, unsigned long nreturn false; } -static __always_inline void do_syscall_x32(struct pt_regs *regs, unsigned long nr) +static __always_inline bool do_syscall_x32(struct pt_regs *regs, unsigned long nr) { +if (!IS_ENABLED (CONFIG_X86_X32_ABI )) +return false; +/* Adjust the starting offset of the table */ nr -= __X32_SYSCALL_BIT; -if (IS_ENABLED (CONFIG_X86_X32_ABI ) &&likely (nr < X32_NR_syscalls)) { +if (likely (nr < X32_NR_syscalls)) { nr =array_index_nospec (nr, X32_NR_syscalls); regs->ax =x32_sys_call (regs, (unsigned int )nr); +return true; } +return false; }/* Returns true to return using SYSRET, or false to use IRET */
@@ -81,8 +86,21 @@ __visible noinstr bool do_syscall_64(struct pt_regs *regs, long nr)if (likely (syscall_enter_from_user_mode_randomize_stack (regs, &nr))) {instrumentation_begin (); -if (!do_syscall_x64 (regs, nr)) -do_syscall_x32 (regs, nr); +if (unlikely (!do_syscall_x64 (regs, nr))) { +/* +* The special treatment of syscall number -1 is a +* historical bogosity as the original code used -1 to +* indicate syscall abort, which is not distinguishable +* from a syscall which is invoked with syscall number +* -1. The historic behavior is to keep the return value +* in regs->ax unmodified in that case, which means it's +* either the preset value -ENOSYS or a value which was +* written by a tracer. If the syscall number is invalid +* but not -1 then overwrite any tracer modification. +*/ +if (!do_syscall_x32 (regs, nr) && nr !=-1L ) + regs->ax = -ENOSYS ; + }instrumentation_end (); }
Re: [patch 16/18] x86/entry: Get rid of the sys_ni_syscall() indirection
In reply to Thomas GleixnerQuoted 6 lines · Thomas Gleixner
IOW, a tracer modification of
regs->axis not overwritten when the syscall number is out of range.Between 2.6.19-rc2 and -rc3
x86_64was changed to _always_ overwriteregs->axwhen the syscall number is out of range.
Quoted 6 lines
In the 3.8 merge window seccomp introduced the -1 == skip bogosity which got fixed up and made "consistent" in several changes afterwards. Just that it never reached a state of consistency due to the overloading.
So are we stuck with this behavior or do we sit down and define what the correct behavior should be?
I wouldn't say we are stuck. The test did reassemble the status we had at the moment. As you wrote yourself the behaviour changed a few times and not on purpose.
I would say we define what correct behaviour should be and make sure it is consistent across all the architectures.
Quoted 3 lines
Thanks,
tglx
Sebastian
H. Peter Anvin
reviewerRe: [patch 16/18] x86/entry: Get rid of the sys_ni_syscall() indirection
In reply to Thomas GleixnerQuoted 25 lines · Thomas Gleixner
Quoted 12 lines · H. Peter Anvin
arch/x86/entry/syscall_64.c static __always_inline bool do_syscall_x · line 74
Quoted 9 lines · Thomas Gleixner
arch/x86/entry/syscall_64.c +1
-1-static __always_inline void do_syscall_x32(struct pt_regs *regs, unsigned long nr) +static __always_inline bool do_syscall_x32(struct pt_regs *regs, unsigned long nr){
arch/x86/entry/syscall_64.c +6
-0+if (!IS_ENABLED (CONFIG_X86_X32_ABI )) +return false; + +/* Preserve the historic insanity of treating -1 special on x32 */ +if (nr ==ULONG_MAX ) +return true;It was never limited to x32...
Tired brain misread the test output:
[RUN] Running tests under ptrace: modifying the default return
[RUN] Checking system calls with msb = 0 (0x0)[OK] x32 syscalls 0:-64..-2 returned -ENOSYS as expected [OK] x32 syscall 0:-1 returned MODIFIED_BY_PTRACE as expected [OK] x64 syscalls 0:-64..-1 returned -ENOSYS as expectedBut that's because the "-1" on x32 is actually
0xFFFFFFFFwhile on x64 it's0x7FFFFFFF.
Quoted 11 lines
The whole mess comes from using -1 as indicator for syscall abort which is undistinguishable from a syscall(nr=-1).
Bah. Let me restore this nonsense.
Thanks,
tglx
Yeah, that was always a WTF.
Thomas Gleixner
maintainerPATCH 17/18 x86/entry: Simplify the syscall number logic
In reply to Thomas GleixnerConverting from int to long, back to int and then to unsigned int is confusing at best.
None of this voodoo is required. Negative syscall numbers including -1 don't need any of this treatment and the low level ASM code already does the sign extension to 64-bit on a 64-bit kernel.
The only point where signedness matters is the comparison against the maximum syscall number, but that can be simplified by just using a unsigned argument for the various syscall invocation functions.
--- arch/x86/entry/syscall_32.c | 26 +++++++++++--------------- arch/x86/entry/syscall_64.c | 36 ++++++++++++++---------------------- arch/x86/include/asm/syscall.h | 2 +- 3 files changed, 26 insertions(+), 38 deletions(-)
arch/x86/entry/syscall_32.c +11 -15
@@ -41,6 +41,8 @@ const sys_call_ptr_t sys_call_table[] =#endif #define __SYSCALL (nr, sym) case nr: return __ia32_##sym(regs); + +/* The unsigned int @nr argument is intentional as it creates denser code in a 64-bit build */ static noinline long ia32_sys_call (const struct pt_regs *regs,unsigned int nr) {switch (nr) {
@@ -49,7 +51,7 @@ static noinline long ia32_sys_call(const } } -static __always_inline int syscall_32_enter(struct pt_regs *regs) +static __always_inline long syscall_32_enter (struct pt_regs *regs) {if (IS_ENABLED (CONFIG_IA32_EMULATION ))current_thread_info ()->status |=TS_COMPAT ;
@@ -70,17 +72,11 @@ early_param("ia32_emulation", ia32_emula/* * Invoke a 32-bit syscall. Called with IRQs on in CT_STATE_KERNEL. */ -static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, int nr) +static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, unsigned long nr) { -/* -* Convert negative numbers to very high and thus out of range -* numbers for comparisons. -*/ -unsigned int unr = nr; - -if (likely (unr < IA32_NR_syscalls)) { - unr =array_index_nospec (unr, IA32_NR_syscalls); - regs->ax =ia32_sys_call (regs, unr); +if (likely (nr < IA32_NR_syscalls)) { + nr =array_index_nospec (nr, IA32_NR_syscalls); + regs->ax =ia32_sys_call (regs, (unsigned int )nr); } }
@@ -126,7 +122,7 @@ static __always_inline bool int80_is_ext*/ __visible noinstr void do_int80_emulation(struct pt_regs *regs) { -int nr; +long nr;/* Kernel does not use INT $0x80! */ if (unlikely (!user_mode (regs))) {
@@ -205,7 +201,7 @@ static __always_inline bool int80_is_ext*/ DEFINE_FREDENTRY_RAW (int80_emulation) { -int nr; +long nr;enter_from_user_mode_randomize_stack (regs);
@@ -240,7 +236,7 @@ DEFINE_FREDENTRY_RAW(int80_emulation)/* Handles int $0x80 on a 32bit kernel */ __visible noinstr void do_int80_syscall_32(struct pt_regs *regs) { -int nr =syscall_32_enter (regs); +long nr =syscall_32_enter (regs);/* * Subtlety here: if ptrace pokes something larger than 2^31-1 into
@@ -260,7 +256,7 @@ DEFINE_FREDENTRY_RAW(int80_emulation) static noinstr bool __do_fast_syscall_32(struct pt_regs *regs) { -int nr =syscall_32_enter (regs); +long nr =syscall_32_enter (regs);int res;enter_from_user_mode_randomize_stack (regs);
arch/x86/entry/syscall_64.c +14 -22
@@ -32,6 +32,8 @@ const sys_call_ptr_t sys_call_table[] =#undef __SYSCALL#define __SYSCALL (nr, sym) case nr: return __x64_##sym(regs); + +/* The unsigned int @nr argument is intentional as it creates denser code */ static noinline long x64_sys_call (const struct pt_regs *regs,unsigned int nr) {switch (nr) {
@@ -52,39 +54,29 @@ static noinline long x32_sys_call(const#endif } -static __always_inline bool do_syscall_x64(struct pt_regs *regs, int nr) +static __always_inline bool do_syscall_x64(struct pt_regs *regs, unsigned long nr) { -/* -* Convert negative numbers to very high and thus out of range -* numbers for comparisons. -*/ -unsigned int unr = nr; - -if (likely (unr < NR_syscalls)) { - unr =array_index_nospec (unr, NR_syscalls); - regs->ax =x64_sys_call (regs, unr); +if (likely (nr < NR_syscalls)) { + nr =array_index_nospec (nr, NR_syscalls); + regs->ax =x64_sys_call (regs, (unsigned int )nr);return true; }return false; } -static __always_inline void do_syscall_x32(struct pt_regs *regs, int nr) +static __always_inline void do_syscall_x32(struct pt_regs *regs, unsigned long nr) { -/* -* Adjust the starting offset of the table, and convert numbers -* < __X32_SYSCALL_BIT to very high and thus out of range -* numbers for comparisons. -*/ -unsigned int xnr = nr - __X32_SYSCALL_BIT; - -if (IS_ENABLED (CONFIG_X86_X32_ABI ) &&likely (xnr < X32_NR_syscalls)) { - xnr =array_index_nospec (xnr, X32_NR_syscalls); - regs->ax =x32_sys_call (regs, xnr); +/* Adjust the starting offset of the table */ + nr -= __X32_SYSCALL_BIT; + +if (IS_ENABLED (CONFIG_X86_X32_ABI ) &&likely (nr < X32_NR_syscalls)) { + nr =array_index_nospec (nr, X32_NR_syscalls); + regs->ax =x32_sys_call (regs, (unsigned int )nr); } }/* Returns true to return using SYSRET, or false to use IRET */ -__visible noinstr bool do_syscall_64(struct pt_regs *regs, int nr) +__visible noinstr bool do_syscall_64(struct pt_regs *regs, long nr) { nr =syscall_enter_from_user_mode_randomize_stack (regs, nr);
arch/x86/include/asm/syscall.h +1 -1
@@ -164,7 +164,7 @@ static inline int syscall_get_arch(struc ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; } -bool do_syscall_64 (struct pt_regs *regs,int nr); +bool do_syscall_64 (struct pt_regs *regs,long nr);void do_int80_emulation (struct pt_regs *regs);#endif /* CONFIG_X86_32 */
[tip: core/entry] x86/entry: Simplify the syscall number logic
The following commit has been merged into the core/entry branch of tip:
The following commit has been merged into the core/entry branch of tip:
Commit-ID: fb419d53f2619e29bf4f96613d9a614e1c263736 Gitweb: https://git.kernel.org/tip/fb419d53f2619e29bf4f96613d9a614e1c263736 Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 07 Jul 2026 21:07:05 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Sun, 12 Jul 2026 12:38:02 +02:00
x86/entry: Simplify the syscall number logic
Converting from int to long, back to int and then to unsigned int is confusing at best.
None of this voodoo is required. Negative syscall numbers including -1 don't need any of this treatment and the low level ASM code already does the sign extension to 64-bit on a 64-bit kernel.
The only point where signedness matters is the comparison against the maximum syscall number, but that can be simplified by just using a unsigned argument for the various syscall invocation functions.
--- arch/x86/entry/syscall_32.c | 26 ++++++++++--------------- arch/x86/entry/syscall_64.c | 34 ++++++++++++--------------------- arch/x86/include/asm/syscall.h | 2 +- 3 files changed, 25 insertions(+), 37 deletions(-)
arch/x86/entry/syscall_32.c +11 -15
@@ -41,6 +41,8 @@ const sys_call_ptr_t sys_call_table[] = {#endif #define __SYSCALL (nr, sym) case nr: return __ia32_##sym(regs); + +/* The unsigned int @nr argument is intentional as it creates denser code in a 64-bit build */ static noinline long ia32_sys_call (const struct pt_regs *regs,unsigned int nr) {switch (nr) {
@@ -49,7 +51,7 @@ static noinline long ia32_sys_call(const struct pt_regs *regs, unsigned int nr) } } -static __always_inline int syscall_32_enter(struct pt_regs *regs) +static __always_inline long syscall_32_enter (struct pt_regs *regs) {if (IS_ENABLED (CONFIG_IA32_EMULATION ))current_thread_info ()->status |=TS_COMPAT ;
@@ -70,17 +72,11 @@ early_param("ia32_emulation", ia32_emulation_override_cmdline);/* * Invoke a 32-bit syscall. Called with IRQs on in CT_STATE_KERNEL. */ -static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, int nr) +static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, unsigned long nr) { -/* -* Convert negative numbers to very high and thus out of range -* numbers for comparisons. -*/ -unsigned int unr = nr; - -if (likely (unr < IA32_NR_syscalls)) { - unr =array_index_nospec (unr, IA32_NR_syscalls); - regs->ax =ia32_sys_call (regs, unr); +if (likely (nr < IA32_NR_syscalls)) { + nr =array_index_nospec (nr, IA32_NR_syscalls); + regs->ax =ia32_sys_call (regs, (unsigned int )nr); } }
@@ -126,7 +122,7 @@ static __always_inline bool int80_is_external(void)*/ __visible noinstr void do_int80_emulation(struct pt_regs *regs) { -int nr; +long nr;/* Kernel does not use INT $0x80! */ if (unlikely (!user_mode (regs))) {
@@ -205,7 +201,7 @@ __visible noinstr void do_int80_emulation(struct pt_regs *regs)*/ DEFINE_FREDENTRY_RAW (int80_emulation) { -int nr; +long nr;enter_from_user_mode_randomize_stack (regs);
@@ -240,7 +236,7 @@ DEFINE_FREDENTRY_RAW(int80_emulation)/* Handles int $0x80 on a 32bit kernel */ __visible noinstr void do_int80_syscall_32(struct pt_regs *regs) { -int nr =syscall_32_enter (regs); +long nr =syscall_32_enter (regs);/* * Subtlety here: if ptrace pokes something larger than 2^31-1 into
@@ -260,7 +256,7 @@ __visible noinstr void do_int80_syscall_32(struct pt_regs *regs) static noinstr bool __do_fast_syscall_32(struct pt_regs *regs) { -int nr =syscall_32_enter (regs); +long nr =syscall_32_enter (regs);int res;enter_from_user_mode_randomize_stack (regs);
arch/x86/entry/syscall_64.c +13 -21
@@ -32,6 +32,8 @@ const sys_call_ptr_t sys_call_table[] = {#undef __SYSCALL#define __SYSCALL (nr, sym) case nr: return __x64_##sym(regs); + +/* The unsigned int @nr argument is intentional as it creates denser code */ static noinline long x64_sys_call (const struct pt_regs *regs,unsigned int nr) {switch (nr) {
@@ -52,39 +54,29 @@ static noinline long x32_sys_call(const struct pt_regs *regs, unsigned int nr)#endif } -static __always_inline bool do_syscall_x64(struct pt_regs *regs, int nr) +static __always_inline bool do_syscall_x64(struct pt_regs *regs, unsigned long nr) { -/* -* Convert negative numbers to very high and thus out of range -* numbers for comparisons. -*/ -unsigned int unr = nr; - -if (likely (unr < NR_syscalls)) { - unr =array_index_nospec (unr, NR_syscalls); - regs->ax =x64_sys_call (regs, unr); +if (likely (nr < NR_syscalls)) { + nr =array_index_nospec (nr, NR_syscalls); + regs->ax =x64_sys_call (regs, (unsigned int )nr);return true; }return false; } -static __always_inline void do_syscall_x32(struct pt_regs *regs, int nr) +static __always_inline void do_syscall_x32(struct pt_regs *regs, unsigned long nr) { -/* -* Adjust the starting offset of the table, and convert numbers -* < __X32_SYSCALL_BIT to very high and thus out of range -* numbers for comparisons. -*/ -unsigned int xnr = nr - __X32_SYSCALL_BIT; +/* Adjust the starting offset of the table */ + nr -= __X32_SYSCALL_BIT; -if (IS_ENABLED (CONFIG_X86_X32_ABI ) &&likely (xnr < X32_NR_syscalls)) { - xnr =array_index_nospec (xnr, X32_NR_syscalls); - regs->ax =x32_sys_call (regs, xnr); +if (IS_ENABLED (CONFIG_X86_X32_ABI ) &&likely (nr < X32_NR_syscalls)) { + nr =array_index_nospec (nr, X32_NR_syscalls); + regs->ax =x32_sys_call (regs, (unsigned int )nr); } }/* Returns true to return using SYSRET, or false to use IRET */ -__visible noinstr bool do_syscall_64(struct pt_regs *regs, int nr) +__visible noinstr bool do_syscall_64(struct pt_regs *regs, long nr) { nr =syscall_enter_from_user_mode_randomize_stack (regs, nr);
arch/x86/include/asm/syscall.h +1 -1
@@ -164,7 +164,7 @@ static inline int syscall_get_arch(struct task_struct *task) ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; } -bool do_syscall_64 (struct pt_regs *regs,int nr); +bool do_syscall_64 (struct pt_regs *regs,long nr);void do_int80_emulation (struct pt_regs *regs);#endif /* CONFIG_X86_32 */
Thomas Gleixner
maintainerPATCH 18/18 entry, treewide: Make syscall_enter_from_user_mode[_work]() indicate syscall execution
In reply to Thomas GleixnerFrom: Michal Suchánek <[email protected]>
The return values of syscall_enter_from_user_mode[_work]() are non-intuitive. Both functions return the syscall number which should be invoked by the architecture specific syscall entry code. The returned number can be:
- the unmodified syscall number which was handed in by the caller
- a modified syscall number (ptrace, seccomp, trace/probe/bpf)
That has an additional twist. If the return value is -1L then the caller is not allowed to modify the return value as that indicates that the modifying entity requests to abort the syscall and set the return value already. That can obviously not be differentiated from a syscall which handed in -1 as syscall number.
The established way to deal with that is:
set_return_value(regs, -ENOSYS);
nr = syscall_enter_from_user_mode(regs, nr);
if ((unsigned)nr < SYSCALLNR_MAX)
handle_syscall(regs, nr);
else if (nr != -1)
set_return_value(regs, -ENOSYS);The latter is obviously redundant, but that's just a leftover of the historical evolution of this code. S390 has some special requirements here, which can be avoided when the return value is not ambiguous.
Now that the functions which modify the syscall number and want to abort are converted to indicate that with a boolean return value, it's obvious to hand this through to the callers.
Rework syscall_enter_from_user_mode[_work]) so they take a pointer to the syscall number and return a boolean, which indicates whether the syscall should be handled or not.
That's not only more intuitive, it also results in slightly denser executable code on x86 at least, but perf results are neutral and within the noise.
[ tglx: Adopted it to the changes in the generic entry code, fixed up the
32-bit fallout and rewrote change log ]
--- Documentation/core-api/entry.rst | 18 +++++++++++------- arch/loongarch/kernel/syscall.c | 14 +++++++------- arch/powerpc/kernel/syscall.c | 3 ++- arch/riscv/kernel/traps.c | 11 +++++------ arch/s390/kernel/syscall.c | 7 +++++-- arch/x86/entry/syscall_32.c | 25 ++++++++++++------------- arch/x86/entry/syscall_64.c | 12 ++++++------ include/linux/entry-common.h | 12 +++++------- 8 files changed, 53 insertions(+), 49 deletions(-)
Documentation/core-api/entry.rst +11 -7
@@ -68,16 +68,20 @@ low-level C code must not be instrumente noinstr void syscall(struct pt_regs *regs, int nr) { arch_syscall_enter(regs); - nr = syscall_enter_from_user_mode_randomize_stack(regs, nr); - - instrumentation_begin(); - if (!invoke_syscall(regs, nr) && nr != -1) - result_reg(regs) = __sys_ni_syscall(regs); - instrumentation_end(); - + result_reg(regs) = -ENOSYS; + if (syscall_enter_from_user_mode_randomize_stack(regs, &nr)) { + instrumentation_begin(); + if (!invoke_syscall(regs, nr)) + result_reg(regs) = __sys_ni_syscall(regs); + instrumentation_end(); + } syscall_exit_to_user_mode(regs); } +It is required that either the low level assembly code or the syscall +function sets the result register to -ENOSYS before invoking the generic +code. + syscall_enter_from_user_mode_randomize_stack() first invokes enter_from_user_mode_randomize_stack() which establishes state in the following order:
arch/loongarch/kernel/syscall.c +7 -7
@@ -57,8 +57,8 @@ typedef long (*sys_call_fn)(unsigned lon void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) { -unsigned long nr;sys_call_fn syscall_fn; +unsigned long nr; nr = regs->regs[11 ];/* Set for syscall restarting */
@@ -69,12 +69,12 @@ void noinstr __no_stack_protector do_sys regs->orig_a0 = regs->regs[4 ]; regs->regs[4 ] = -ENOSYS ; - nr =syscall_enter_from_user_mode_randomize_stack (regs, nr); - -if (nr < NR_syscalls) { - syscall_fn = sys_call_table[array_index_nospec (nr, NR_syscalls)]; - regs->regs[4 ] =syscall_fn (regs->orig_a0, regs->regs[5 ], regs->regs[6 ], - regs->regs[7 ], regs->regs[8 ], regs->regs[9 ]); +if (likely (syscall_enter_from_user_mode_randomize_stack (regs, &nr))) { +if (nr < NR_syscalls) { + syscall_fn = sys_call_table[array_index_nospec (nr, NR_syscalls)]; + regs->regs[4 ] =syscall_fn (regs->orig_a0, regs->regs[5 ], regs->regs[6 ], + regs->regs[7 ], regs->regs[8 ], regs->regs[9 ]); + } }syscall_exit_to_user_mode (regs);
arch/powerpc/kernel/syscall.c +2 -1
@@ -18,7 +18,8 @@ notrace long system_call_exception(struclong ret;syscall_fn f; - r0 =syscall_enter_from_user_mode_randomize_stack (regs, r0); + if (unlikely(!syscall_enter_from_user_mode_randomize_stack(regs, &r0)) +return syscall_get_error (current, regs);if (unlikely (r0 >= NR_syscalls)) {if (unlikely (trap_is_unsupported_scv (regs))) {
arch/riscv/kernel/traps.c +5 -6
@@ -332,13 +332,12 @@ void do_trap_ecall_u(struct pt_regs *regriscv_v_vstate_discard (regs); - syscall =syscall_enter_from_user_mode_randomize_stack (regs, syscall); - -if (syscall >=0 && syscall < NR_syscalls) { - syscall =array_index_nospec (syscall, NR_syscalls); -syscall_handler (regs, syscall); +if (syscall_enter_from_user_mode_randomize_stack (regs, &syscall)) { +if (syscall >=0 && syscall < NR_syscalls) { + syscall =array_index_nospec (syscall, NR_syscalls); +syscall_handler (regs, syscall); + } } -syscall_exit_to_user_mode (regs); }else {irqentry_state_t state =irqentry_nmi_enter (regs);
arch/s390/kernel/syscall.c +5 -2
@@ -96,6 +96,7 @@ SYSCALL_DEFINE0(ni_syscall) void noinstr __do_syscall(struct pt_regs *regs, int per_trap) {unsigned long nr; +bool permit;enter_from_user_mode_randomize_stack (regs);
@@ -121,7 +122,9 @@ void noinstr __do_syscall(struct pt_regs regs->psw.addr = current->restart_block.arch_data; current->restart_block.arch_data =1 ; } - nr =syscall_enter_from_user_mode_work (regs, nr); + + permit =syscall_enter_from_user_mode_work (regs, &nr); +/* * In the s390 ptrace ABI, both the syscall number and the return value * use gpr2. However, userspace puts the syscall number either in the
@@ -129,7 +132,7 @@ void noinstr __do_syscall(struct pt_regs* work, the ptrace code sets PIF_SYSCALL_RET_SET, which is checked here * and if set, the syscall will be skipped. */ -if (unlikely (test_and_clear_pt_regs_flag (regs,PIF_SYSCALL_RET_SET ))) +if (unlikely (test_and_clear_pt_regs_flag (regs,PIF_SYSCALL_RET_SET ) || !permit)) goto out; regs->gprs[2 ] = -ENOSYS ;if (likely (nr < NR_syscalls)) {
arch/x86/entry/syscall_32.c +12 -13
@@ -161,8 +161,9 @@ static __always_inline bool int80_is_ext nr =syscall_32_enter (regs);local_irq_enable (); - nr =syscall_enter_from_user_mode_work (regs, nr); -do_syscall_32_irqs_on (regs, nr); + +if (likely (syscall_enter_from_user_mode_work (regs, &nr))) +do_syscall_32_irqs_on (regs, nr);instrumentation_end ();syscall_exit_to_user_mode (regs);
@@ -223,8 +224,8 @@ DEFINE_FREDENTRY_RAW(int80_emulation) nr =syscall_32_enter (regs);local_irq_enable (); - nr =syscall_enter_from_user_mode_work (regs, nr); -do_syscall_32_irqs_on (regs, nr); +if (likely (syscall_enter_from_user_mode_work (regs, &nr))) +do_syscall_32_irqs_on (regs, nr);instrumentation_end ();syscall_exit_to_user_mode (regs);
@@ -243,13 +244,13 @@ DEFINE_FREDENTRY_RAW(int80_emulation)* orig_ax, the int return value truncates it. This matches * the semantics of syscall_get_nr(). */ - nr =syscall_enter_from_user_mode_randomize_stack (regs, nr); - -instrumentation_begin (); +if (likely (syscall_enter_from_user_mode_randomize_stack (regs, &nr))) { +instrumentation_begin (); -do_syscall_32_irqs_on (regs, nr); +do_syscall_32_irqs_on (regs, nr); -instrumentation_end (); +instrumentation_end (); + } syscall_exit_to_user_mode(regs); }#endif /* !CONFIG_IA32_EMULATION */
@@ -286,10 +287,8 @@ static noinstr bool __do_fast_syscall_32return false; } - nr =syscall_enter_from_user_mode_work (regs, nr); - -/* Now this is just like a normal syscall. */ -do_syscall_32_irqs_on (regs, nr); +if (likely (syscall_enter_from_user_mode_work (regs, &nr))) +do_syscall_32_irqs_on (regs, nr);instrumentation_end ();syscall_exit_to_user_mode (regs);
arch/x86/entry/syscall_64.c +6 -6
@@ -78,14 +78,14 @@ static __always_inline void do_syscall_x/* Returns true to return using SYSRET, or false to use IRET */ __visible noinstr bool do_syscall_64(struct pt_regs *regs, long nr) { - nr =syscall_enter_from_user_mode_randomize_stack (regs, nr); +if (likely (syscall_enter_from_user_mode_randomize_stack (regs, &nr))) { +instrumentation_begin (); -instrumentation_begin (); +if (!do_syscall_x64 (regs, nr)) +do_syscall_x32 (regs, nr); -if (!do_syscall_x64 (regs, nr)) -do_syscall_x32 (regs, nr); - -instrumentation_end (); +instrumentation_end (); + }syscall_exit_to_user_mode (regs);/*
include/linux/entry-common.h +5 -7
@@ -71,7 +71,7 @@ static inline void syscall_enter_audit(s } } -static __always_inline bool syscall_trace_enter(struct pt_regs *regs, unsigned long work, +static __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work,long *syscall) {/*
@@ -141,16 +141,14 @@ static __always_inline bool syscall_trac* ptrace_report_syscall_permit_entry(), __seccomp_permit_syscall(), trace_sys_enter() * 2) Invocation of audit_syscall_entry() */ -static __always_inline long syscall_enter_from_user_mode_work (struct pt_regs *regs,long syscall) +static __always_inline bool syscall_enter_from_user_mode_work(struct pt_regs *regs, long *syscall) {unsigned long work =READ_ONCE (current_thread_info ()->syscall_work); -if (work &SYSCALL_WORK_ENTER ) { -if (!syscall_trace_enter (regs, work, &syscall)) -return -1L ; - } +if (unlikely (work &SYSCALL_WORK_ENTER )) +return syscall_trace_enter (regs, work, syscall); -return syscall; +return true; }/**
Shrikanth Hegde
reviewerRe: [patch 18/18] entry, treewide: Make syscall_enter_from_user_mode[_work]() indicate syscall execution
Hi Thomas.
Quoted 136 lines · Thomas Gleixner
From: Michal Suchánek <[email protected]>
The return values of syscall_enter_from_user_mode[_work]() are non-intuitive. Both functions return the syscall number which should be invoked by the architecture specific syscall entry code. The returned number can be:
- the unmodified syscall number which was handed in by the caller
- a modified syscall number (ptrace, seccomp, trace/probe/bpf)
That has an additional twist. If the return value is -1L then the caller is not allowed to modify the return value as that indicates that the modifying entity requests to abort the syscall and set the return value already. That can obviously not be differentiated from a syscall which handed in -1 as syscall number.
The established way to deal with that is:
set_return_value(regs, -ENOSYS); nr = syscall_enter_from_user_mode(regs, nr); if ((unsigned)nr < SYSCALLNR_MAX) handle_syscall(regs, nr); else if (nr != -1) set_return_value(regs, -ENOSYS);The latter is obviously redundant, but that's just a leftover of the historical evolution of this code. S390 has some special requirements here, which can be avoided when the return value is not ambiguous.
Now that the functions which modify the syscall number and want to abort are converted to indicate that with a boolean return value, it's obvious to hand this through to the callers.
Rework syscall_enter_from_user_mode[_work]) so they take a pointer to the syscall number and return a boolean, which indicates whether the syscall should be handled or not.
That's not only more intuitive, it also results in slightly denser executable code on x86 at least, but perf results are neutral and within the noise.
[ tglx: Adopted it to the changes in the generic entry code, fixed up the
32-bit fallout and rewrote change log ]Signed-off-by Michal Suchánek <[email protected]>Signed-off-by Thomas Gleixner <[email protected]>Cc Jonathan Corbet <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Mark Rutland <[email protected]>Cc Huacai Chen <[email protected]>Cc Michael Ellerman <[email protected]>Cc Shrikanth Hegde <[email protected]>Cc Paul Walmsley <[email protected]>Cc Palmer Dabbelt <[email protected]>Cc Sven Schnelle <[email protected]>--- Documentation/core-api/entry.rst | 18 +++++++++++------- arch/loongarch/kernel/syscall.c | 14 +++++++------- arch/powerpc/kernel/syscall.c | 3 ++- arch/riscv/kernel/traps.c | 11 +++++------ arch/s390/kernel/syscall.c | 7 +++++-- arch/x86/entry/syscall_32.c | 25 ++++++++++++------------- arch/x86/entry/syscall_64.c | 12 ++++++------ include/linux/entry-common.h | 12 +++++------- 8 files changed, 53 insertions(+), 49 deletions(-)Documentation/core-api/entry.rst +11
-7@@ -68,16 +68,20 @@ low-level C code must not be instrumente noinstr void syscall(struct pt_regs *regs, int nr) { arch_syscall_enter(regs); - nr = syscall_enter_from_user_mode_randomize_stack(regs, nr); - - instrumentation_begin(); - if (!invoke_syscall(regs, nr) && nr != -1) - result_reg(regs) = __sys_ni_syscall(regs); - instrumentation_end(); - + result_reg(regs) = -ENOSYS; + if (syscall_enter_from_user_mode_randomize_stack(regs, &nr)) { + instrumentation_begin(); + if (!invoke_syscall(regs, nr)) + result_reg(regs) = __sys_ni_syscall(regs); + instrumentation_end(); + } syscall_exit_to_user_mode(regs); } +It is required that either the low level assembly code or the syscall +function sets the result register to -ENOSYS before invoking the generic +code. + syscall_enter_from_user_mode_randomize_stack() first invokes enter_from_user_mode_randomize_stack() which establishes state in the following order:arch/loongarch/kernel/syscall.c +7
-7@@ -57,8 +57,8 @@ typedef long (*sys_call_fn)(unsigned lon void noinstr __no_stack_protector do_syscall(struct pt_regs *regs) { -unsigned long nr;sys_call_fn syscall_fn; +unsigned long nr; nr = regs->regs[11 ];/* Set for syscall restarting */ @@ -69,12 +69,12 @@ void noinstr __no_stack_protector do_sys regs->orig_a0 = regs->regs[4 ]; regs->regs[4 ] = -ENOSYS ; - nr =syscall_enter_from_user_mode_randomize_stack (regs, nr); - -if (nr < NR_syscalls) { - syscall_fn = sys_call_table[array_index_nospec (nr, NR_syscalls)]; - regs->regs[4 ] =syscall_fn (regs->orig_a0, regs->regs[5 ], regs->regs[6 ], - regs->regs[7 ], regs->regs[8 ], regs->regs[9 ]); +if (likely (syscall_enter_from_user_mode_randomize_stack (regs, &nr))) { +if (nr < NR_syscalls) { + syscall_fn = sys_call_table[array_index_nospec (nr, NR_syscalls)]; + regs->regs[4 ] =syscall_fn (regs->orig_a0, regs->regs[5 ], regs->regs[6 ], + regs->regs[7 ], regs->regs[8 ], regs->regs[9 ]); + } }syscall_exit_to_user_mode (regs);
arch/powerpc/kernel/syscall.c notrace long system_call_exception(struc · line 23
Quoted 7 lines
arch/powerpc/kernel/syscall.c +2
-1@@ -18,7 +18,8 @@ notrace long system_call_exception(struclong ret;syscall_fn f; - r0 =syscall_enter_from_user_mode_randomize_stack (regs, r0); + if (unlikely(!syscall_enter_from_user_mode_randomize_stack(regs, &r0)) +return syscall_get_error (current, regs);
There is one missing )
arch/powerpc/kernel/syscall.c +1 -1
@@ -18,7 +18,7 @@ notrace long system_call_exception(struct pt_regs *regs, unsigned long r0)long ret;syscall_fn f; - if (unlikely(!syscall_enter_from_user_mode_randomize_stack(regs, &r0)) +if (unlikely (!syscall_enter_from_user_mode_randomize_stack (regs, &r0)))return syscall_get_error (current, regs);if (unlikely (r0 >= NR_syscalls)) {
Quoted 166 lines
arch/powerpc/kernel/syscall.c +0
-0if (unlikely (r0 >= NR_syscalls)) {if (unlikely (trap_is_unsupported_scv (regs))) {arch/riscv/kernel/traps.c +5
-6@@ -332,13 +332,12 @@ void do_trap_ecall_u(struct pt_regs *regriscv_v_vstate_discard (regs); - syscall =syscall_enter_from_user_mode_randomize_stack (regs, syscall); - -if (syscall >=0 && syscall < NR_syscalls) { - syscall =array_index_nospec (syscall, NR_syscalls); -syscall_handler (regs, syscall); +if (syscall_enter_from_user_mode_randomize_stack (regs, &syscall)) { +if (syscall >=0 && syscall < NR_syscalls) { + syscall =array_index_nospec (syscall, NR_syscalls); +syscall_handler (regs, syscall); + } } -syscall_exit_to_user_mode (regs); }else {irqentry_state_t state =irqentry_nmi_enter (regs);arch/s390/kernel/syscall.c +5
-2@@ -96,6 +96,7 @@ SYSCALL_DEFINE0(ni_syscall) void noinstr __do_syscall(struct pt_regs *regs, int per_trap) {unsigned long nr; +bool permit;enter_from_user_mode_randomize_stack (regs);@@ -121,7 +122,9 @@ void noinstr __do_syscall(struct pt_regs regs->psw.addr = current->restart_block.arch_data; current->restart_block.arch_data =1 ; } - nr =syscall_enter_from_user_mode_work (regs, nr); + + permit =syscall_enter_from_user_mode_work (regs, &nr); +/* * In the s390 ptrace ABI, both the syscall number and the return value * use gpr2. However, userspace puts the syscall number either in the @@ -129,7 +132,7 @@ void noinstr __do_syscall(struct pt_regs* work, the ptrace code sets PIF_SYSCALL_RET_SET, which is checked here * and if set, the syscall will be skipped. */ -if (unlikely (test_and_clear_pt_regs_flag (regs,PIF_SYSCALL_RET_SET ))) +if (unlikely (test_and_clear_pt_regs_flag (regs,PIF_SYSCALL_RET_SET ) || !permit)) goto out; regs->gprs[2 ] = -ENOSYS ;if (likely (nr < NR_syscalls)) {arch/x86/entry/syscall_32.c +12
-13@@ -161,8 +161,9 @@ static __always_inline bool int80_is_ext nr =syscall_32_enter (regs);local_irq_enable (); - nr =syscall_enter_from_user_mode_work (regs, nr); -do_syscall_32_irqs_on (regs, nr); + +if (likely (syscall_enter_from_user_mode_work (regs, &nr))) +do_syscall_32_irqs_on (regs, nr);instrumentation_end ();syscall_exit_to_user_mode (regs);@@ -223,8 +224,8 @@ DEFINE_FREDENTRY_RAW(int80_emulation) nr =syscall_32_enter (regs);local_irq_enable (); - nr =syscall_enter_from_user_mode_work (regs, nr); -do_syscall_32_irqs_on (regs, nr); +if (likely (syscall_enter_from_user_mode_work (regs, &nr))) +do_syscall_32_irqs_on (regs, nr);instrumentation_end ();syscall_exit_to_user_mode (regs);@@ -243,13 +244,13 @@ DEFINE_FREDENTRY_RAW(int80_emulation)* orig_ax, the int return value truncates it. This matches * the semantics of syscall_get_nr(). */ - nr =syscall_enter_from_user_mode_randomize_stack (regs, nr); - -instrumentation_begin (); +if (likely (syscall_enter_from_user_mode_randomize_stack (regs, &nr))) { +instrumentation_begin (); -do_syscall_32_irqs_on (regs, nr); +do_syscall_32_irqs_on (regs, nr); -instrumentation_end (); +instrumentation_end (); + } syscall_exit_to_user_mode(regs); }#endif /* !CONFIG_IA32_EMULATION */ @@ -286,10 +287,8 @@ static noinstr bool __do_fast_syscall_32return false; } - nr =syscall_enter_from_user_mode_work (regs, nr); - -/* Now this is just like a normal syscall. */ -do_syscall_32_irqs_on (regs, nr); +if (likely (syscall_enter_from_user_mode_work (regs, &nr))) +do_syscall_32_irqs_on (regs, nr);instrumentation_end ();syscall_exit_to_user_mode (regs);arch/x86/entry/syscall_64.c +6
-6@@ -78,14 +78,14 @@ static __always_inline void do_syscall_x/* Returns true to return using SYSRET, or false to use IRET */ __visible noinstr bool do_syscall_64(struct pt_regs *regs, long nr) { - nr =syscall_enter_from_user_mode_randomize_stack (regs, nr); +if (likely (syscall_enter_from_user_mode_randomize_stack (regs, &nr))) { +instrumentation_begin (); -instrumentation_begin (); +if (!do_syscall_x64 (regs, nr)) +do_syscall_x32 (regs, nr); -if (!do_syscall_x64 (regs, nr)) -do_syscall_x32 (regs, nr); - -instrumentation_end (); +instrumentation_end (); + }syscall_exit_to_user_mode (regs);/* include/linux/entry-common.h +5
-7@@ -71,7 +71,7 @@ static inline void syscall_enter_audit(s } } -static __always_inline bool syscall_trace_enter(struct pt_regs *regs, unsigned long work, +static __always_inline long syscall_trace_enter (struct pt_regs *regs,unsigned long work,long *syscall) {/* @@ -141,16 +141,14 @@ static __always_inline bool syscall_trac* ptrace_report_syscall_permit_entry(), __seccomp_permit_syscall(), trace_sys_enter() * 2) Invocation of audit_syscall_entry() */ -static __always_inline long syscall_enter_from_user_mode_work (struct pt_regs *regs,long syscall) +static __always_inline bool syscall_enter_from_user_mode_work(struct pt_regs *regs, long *syscall) {unsigned long work =READ_ONCE (current_thread_info ()->syscall_work); -if (work &SYSCALL_WORK_ENTER ) { -if (!syscall_trace_enter (regs, work, &syscall)) -return -1L ; - } +if (unlikely (work &SYSCALL_WORK_ENTER )) +return syscall_trace_enter (regs, work, syscall); -return syscall; +return true; }/**
Thomas Gleixner
maintainerRe: [patch 18/18] entry, treewide: Make syscall_enter_from_user_mode[_work]() indicate syscall execution
Quoted 7 lines · Shrikanth Hegde
Review
Quoted 4 lines · Thomas Gleixner
(quoted diff) +2
-1- r0 = syscall_enter_from_user_mode_randomize_stack(regs, r0); + if (unlikely(!syscall_enter_from_user_mode_randomize_stack(regs, &r0)) + return syscall_get_error(current, regs);There is one missing )
Bah.
Re: [patch 18/18] entry, treewide: Make syscall_enter_from_user_mode[_work]() indicate syscall execution
In reply to Thomas GleixnerQuoted 73 lines · Thomas Gleixner
From: Michal Suchánek <[email protected]>
The return values of syscall_enter_from_user_mode[_work]() are non-intuitive. Both functions return the syscall number which should be invoked by the architecture specific syscall entry code. The returned number can be:
- the unmodified syscall number which was handed in by the caller
- a modified syscall number (ptrace, seccomp, trace/probe/bpf)
That has an additional twist. If the return value is -1L then the caller is not allowed to modify the return value as that indicates that the modifying entity requests to abort the syscall and set the return value already. That can obviously not be differentiated from a syscall which handed in -1 as syscall number.
The established way to deal with that is:
set_return_value(regs, -ENOSYS); nr = syscall_enter_from_user_mode(regs, nr); if ((unsigned)nr < SYSCALLNR_MAX) handle_syscall(regs, nr); else if (nr != -1) set_return_value(regs, -ENOSYS);The latter is obviously redundant, but that's just a leftover of the historical evolution of this code. S390 has some special requirements here, which can be avoided when the return value is not ambiguous.
Now that the functions which modify the syscall number and want to abort are converted to indicate that with a boolean return value, it's obvious to hand this through to the callers.
Rework syscall_enter_from_user_mode[_work]) so they take a pointer to the syscall number and return a boolean, which indicates whether the syscall should be handled or not.
That's not only more intuitive, it also results in slightly denser executable code on x86 at least, but perf results are neutral and within the noise.
[ tglx: Adopted it to the changes in the generic entry code, fixed up the
32-bit fallout and rewrote change log ]Signed-off-by Michal Suchánek <[email protected]>Signed-off-by Thomas Gleixner <[email protected]>Cc Jonathan Corbet <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Mark Rutland <[email protected]>Cc Huacai Chen <[email protected]>Cc Michael Ellerman <[email protected]>Cc Shrikanth Hegde <[email protected]>Cc Paul Walmsley <[email protected]>Cc Palmer Dabbelt <[email protected]>Cc Sven Schnelle <[email protected]>--- Documentation/core-api/entry.rst | 18 +++++++++++------- arch/loongarch/kernel/syscall.c | 14 +++++++------- arch/powerpc/kernel/syscall.c | 3 ++- arch/riscv/kernel/traps.c | 11 +++++------ arch/s390/kernel/syscall.c | 7 +++++-- arch/x86/entry/syscall_32.c | 25 ++++++++++++------------- arch/x86/entry/syscall_64.c | 12 ++++++------ include/linux/entry-common.h | 12 +++++------- 8 files changed, 53 insertions(+), 49 deletions(-)
[...]
arch/powerpc/kernel/syscall.c notrace long system_call_exception(struc · line 21
Quoted 9 lines
(quoted diff) +0
-0syscall_exit_to_user_mode(regs);arch/powerpc/kernel/syscall.c +1
-1@@ -18,7 +18,8 @@ notrace long system_call_exception(struclong ret;syscall_fn f; - r0 =syscall_enter_from_user_mode_randomize_stack (regs, r0); + if (unlikely(!syscall_enter_from_user_mode_randomize_stack(regs, &r0))
Missing one closing ')'.
arch/powerpc/kernel/syscall.c notrace long system_call_exception(struc · line 25
Quoted 4 lines
arch/powerpc/kernel/syscall.c +1
-0+return syscall_get_error (current, regs);if (unlikely (r0 >= NR_syscalls)) {if (unlikely (trap_is_unsupported_scv (regs))) {
Apart from this.
Quoted 150 lines · Thomas Gleixner
Sorry for the long CC list, but this is a treewide change.
Michal recently posted a RFC patch to separate the potential syscall number modifications in
syscall_enter_user_mode_work()from the information whether the syscall should be processed and the return value modified:https://lore.kernel.org/lkml/[email protected]
The existing logic is:
arch_syscall()regs->result = -ENOSYS; syscallnr = syscall_enter_from_user_mode(regs, syscall); if (syscallnr != -1L) regs->result = invoke_syscall(regs, syscall;
syscall_enter_from_user_mode()invokes ptrace, seccomp and tracing/BPF/Probes. All of them can modify the syscall number.ptrace and seccomp explicitly set the syscall number to -1L to indicate that the syscall invocation needs to be skipped and the result has not to be modified as it might have been modified by ptrace or seccomp. The tracer/BPF/Probes mechanism can modify the syscall number as well and relies implicitly on the -1L logic.
This can obviously not be differentiated from a syscall invocation where userspace provided -1 as syscall number.
The general agreement of the discussion was that the current mechanism, while functionally correct is non-intuitive and something like Michals proposal would make that code clearer and easier to handle on the architecture side:
arch_syscall()regs->result = -ENOSYS; if (syscall_enter_from_user_mode(regs, &syscall)) regs->result = invoke_syscall(regs, syscall;That discussion made me look deeper into the related code and as usual there were a lot of other things to discover.
1) Stack randomization
add_random_kstack_offset()can only be invoked afterenter_from_user_mode()established proper state as it calls into instrumentable code.PowerPC got that wrong and the other architectures either invoke it after
enter_from_user_mode()or aftersyscall_enter_from_user_mode().The latter is suboptimal as the randomization takes place after all the user mode entry work. Aside of that
add_random_kstack_offset()uses get/put_cpu_var(), which makes it usable in preemptible code, but when invoked in the interrupt disabled region that's pointless overhead.2) As discussed in the above thread just changing the function signature of syscall_enter_from_user_mode[_work]() so they take a pointer argument for the syscall and then return 0 on success is not really intuitive either. Aside of that this breaks the implicit assumption of the tracer when setting the syscall number to -1.
3) The x86 entry code has some historically accumulated oddities
The following series addresses this by:
1) Providing new [syscall_]enter_from_user_mode() variants, which include stack randomization and utilize a new
add_random_kstack_offset_irqsoff()variant, which avoids the get/put_cpu_var() overhead and converting all usage sites over2) Picking up Jinjie's seccomp patch from:
https://lore.kernel.org/lkml/[email protected]
and addressing the feedback (renaming the seccomp functions)
3) Making the ptrace and tracer related functions return a boolean value to indicate syscall permission
4) Addressing the x86 oddities
5) Converting the tree over to the new scheme
With that all architectures using the generic syscall entry code follow the same scheme, apply stack randomization at the correct and earliest possible place and skip syscall processing depending on the boolean return value of syscall_enter_from_user_mode[_work]().
There should be no functional changes, at least there are none intended.
The resulting text size for the syscall entry code on x8664 is slightly smaller than before these changes.
Testing syscall heavy workloads and micro benchmarks shows a small performance gain for the general rework, but the last patch, which changes the logic to be more understandable has no measurable impact in either direction.
The series applies on Linus tree and is also available from git:
git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.gitentry-rework-v1Thanks,
tglx
--- Documentation/core-api/entry.rst | 33 +++++--- arch/alpha/kernel/ptrace.c | 4 - arch/arc/kernel/ptrace.c | 2 arch/arm/kernel/ptrace.c | 4 - arch/arm64/kernel/ptrace.c | 4 - arch/csky/kernel/ptrace.c | 4 - arch/hexagon/kernel/traps.c | 2 arch/loongarch/kernel/syscall.c | 17 +--- arch/m68k/kernel/ptrace.c | 4 - arch/microblaze/kernel/ptrace.c | 2 arch/mips/kernel/ptrace.c | 4 - arch/nios2/kernel/ptrace.c | 2 arch/openrisc/kernel/ptrace.c | 2 arch/parisc/kernel/ptrace.c | 12 +-- arch/powerpc/kernel/syscall.c | 5 - arch/riscv/kernel/traps.c | 14 +-- arch/s390/kernel/syscall.c | 11 +- arch/sh/kernel/ptrace_32.c | 4 - arch/sparc/kernel/ptrace_32.c | 2 arch/sparc/kernel/ptrace_64.c | 2 arch/um/kernel/ptrace.c | 2 arch/um/kernel/skas/syscall.c | 2 arch/x86/entry/syscall_32.c | 70 +++++++------------ arch/x86/entry/syscall_64.c | 61 ++++++---------- arch/x86/entry/vsyscall/vsyscall_64.c | 14 +-- arch/x86/include/asm/entry-common.h | 1 arch/x86/include/asm/syscall.h | 10 -- arch/xtensa/kernel/ptrace.c | 5 - include/asm-generic/syscall.h | 4 - include/linux/entry-common.h | 125 ++++++++++++++++++++-------------- include/linux/irq-entry-common.h | 6 - include/linux/ptrace.h | 13 +-- include/linux/randomize_kstack.h | 19 +++++ include/linux/seccomp.h | 12 +-- kernel/entry/syscall-common.c | 7 + kernel/seccomp.c | 35 ++++----- 36 files changed, 264 insertions(+), 256 deletions(-)
Quoted 4 lines
_______________________________________________
linux-snps-arc mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-snps-arc
Boot tested this on P11 LPAR and P9 powernv system.
Quoted 11 lines
With that all architectures using the generic syscall entry code follow the same scheme, apply stack randomization at the correct and earliest possible place and skip syscall processing depending on the boolean return value of syscall_enter_from_user_mode[_work]().
There should be no functional changes, at least there are none intended.
The resulting text size for the syscall entry code on x8664 is slightly smaller than before these changes.
Quoted 9 lines
Testing syscall heavy workloads and micro benchmarks shows a small performance gain for the general rework, but the last patch, which changes the logic to be more understandable has no measurable impact in either direction.
The series applies on Linus tree and is also available from git:
git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.gitentry-rework-v1
Hi Thomas,
Thanks for the series.
I have an Alpha GENERIC_ENTRY series posted and planned for the next merge window:
https://lore.kernel.org/linux-alpha/[email protected]/T/#t
Only its final patch intersects with this work.
That patch removes Alpha's architecture-specific syscall_trace_enter() and syscall_trace_leave() implementations, so the Alpha changes in patches 11 and 12 will disappear once the GENERIC_ENTRY conversion is applied.
It also currently uses syscall_enter_from_user_mode(), so I will need to rebase it onto the new entry interface introduced by this series. I expect the integration to be confined to the final GENERIC_ENTRY patch.
The Alpha-specific changes in patches 11 and 12 look correct to me.
Quoted 11 lines
With that all architectures using the generic syscall entry code follow the same scheme, apply stack randomization at the correct and earliest possible place and skip syscall processing depending on the boolean return value of syscall_enter_from_user_mode[_work]().
There should be no functional changes, at least there are none intended.
The resulting text size for the syscall entry code on x8664 is slightly smaller than before these changes.
Quoted 9 lines
Testing syscall heavy workloads and micro benchmarks shows a small performance gain for the general rework, but the last patch, which changes the logic to be more understandable has no measurable impact in either direction.
The series applies on Linus tree and is also available from git:
git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.gitentry-rework-v1
Hi Thomas,
I did another round of testing of this series on Alpha, this time with my Alpha GENERIC_ENTRY conversion rebased on top of this series.
For this test I also manually applied the seccomp fixup discussed earlier in this thread, i.e. fixing the recheck-after-trace logic in __seccomp_filter() along the lines suggested by Jinjie/Oleg.
With that in place, the kernel boots on Alpha and I do not see any regressions in the seccomp_bpf kernel selftest or in the strace testsuite.
One note: the seccomp_bpf selftest run on Alpha uses this not-yet-upstream Alpha selftest enablement patch:
https://lore.kernel.org/linux-alpha/[email protected]/
One Alpha-specific wrinkle I hit while rebasing the GENERIC_ENTRY patch is that Alpha cannot unconditionally pre-seed the normal -ENOSYS return state before calling into the generic entry code: syscall_set_return_value() also updates r19/a3, which is still syscall argument 4 on the normal entry path. Doing that too early broke early userspace mmap() during boot.
The Alpha conversion therefore handles this on the no-dispatch path instead:
after the generic entry helper returns, if the syscall is not to be invoked or the resulting syscall number is invalid, Alpha skips the call, preserves any ptrace/seccomp/BPF-provided return value, and only synthesizes -ENOSYS if the return state was otherwise unchanged. That was needed for the TRACE_syscall.ptrace.syscall_faked and syscall_errno seccomp_bpf cases to pass.
So from the Alpha side, with the seccomp fixup applied:
Are you planning to send a v2 with the seccomp recheck fix and any other review fixups folded in? Is the intention to route this upstream during the next merge window?
Thanks,
Magnus
Thomas Gleixner
maintainerMagnus!
Quoted 5 lines · Magnus Lindholm
One Alpha-specific wrinkle I hit while rebasing the
GENERIC_ENTRYpatch is that Alpha cannot unconditionally pre-seed the normal-ENOSYSreturn state before calling into the generic entry code:syscall_set_return_value()also updates r19/a3, which is still syscall argument 4 on the normal entry path. Doing that too early broke early userspacemmap()during boot.
Similar to what Peter and me suggested in the related discussion vs. s390 which has a similar issue, you can just have a dedicated syscall_return member in your pt_regs struct, which is preset to -ENOSYS and operate on that. You have an unused padding entry there which means it won't even change the size.
Quoted 3 lines
Are you planning to send a v2 with the seccomp recheck fix and any other review fixups folded in? Is the intention to route this upstream during the next merge window?
You were on CC for the V2, no?
The whole pile including Jinjie's seccomp bypass fix is in
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core/entry
and is targeted for the 7.3 merge window.
If you want to base your stuff on that for 7.3, I can add a tag which makes it immutable so it can be pulled into the alpha tree.
Thanks,
tglx
Magnus Lindholm
maintainerThomas,
Quoted 8 lines · Thomas Gleixner
Similar to what Peter and me suggested in the related discussion vs. s390 which has a similar issue, you can just have a dedicated
syscall_returnmember in yourpt_regsstruct, which is preset to-ENOSYSand operate on that. You have an unused padding entry there which means it won't even change the size.
Thanks, that makes sense in principle.
One complication is that my Alpha GENERIC_ENTRY branch already reuses that former pt_regs padding slot, while keeping the pt_regs size and stack alignment unchanged. The extra syscall-entry bookkeeping I needed so far lives in thread_info rather than adding more fields to pt_regs.
So the padding slot is not free in my current branch. I can still look at whether a dedicated syscall_return scratch value would be cleaner, but the tested version currently handles this by setting the default -ENOSYS result only on the no-dispatch path, after generic entry processing, and only if ptrace/seccomp/BPF did not already provide a return value.
Quoted 3 lines
You were on CC for the V2, no?
Sorry, I must have missed that.
Quoted 6 lines
The whole pile including Jinjie's seccomp bypass fix is in
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.gitcore/entryand is targeted for the 7.3 merge window.
Great!
Quoted 3 lines
If you want to base your stuff on that for 7.3, I can add a tag which makes it immutable so it can be pulled into the alpha tree.
Yes, please. There is still some ongoing testing/review of my Alpha GENERIC_ENTRY series, but assuming it is ready in time for the 7.3 merge window, an immutable tag would be very helpful.
Magnus
Thomas Gleixner
maintainerMagnus!
Quoted 7 lines · Magnus Lindholm
Quoted 2 lines · Thomas Gleixner
If you want to base your stuff on that for 7.3, I can add a tag which makes it immutable so it can be pulled into the alpha tree.
Yes, please. There is still some ongoing testing/review of my Alpha
GENERIC_ENTRYseries, but assuming it is ready in time for the 7.3 merge window, an immutable tag would be very helpful.
Here you go:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core-entry-for-arch-07-21-26
Thanks,
tglx
PATCH 1/1 seccomp: Fix syscall skip logic on ptrace
In reply to Thomas Gleixnerseccomp takes a shortcut here. When the syscall number is re-read after ptrace and the sign bit is set in the syscall number the syscall is skipped right away.
This works fairly well on x86 where the return value of the syscall is preset before seccomp is processed.
However, on some architectures the syscall return value overlaps with the syscall number or syscall arguments, and as a result the return value cannot be preset in advance.
For these architectures seccomp needs to exit without flagging the syscall as skipped. Then processing of invalid syscall number in the architecture code should set the return value to -ENOSYS and skip the syscall.
This introduces a change: If the syscall number has the sign bit set, such as -1, previously the filter re-check would not be done, not applying the filter after trace. Now the re-check is done both for syscall nubers with and without sign bit set. This would only make a difference if the syscall number or the filter was changed by the tracer. Otherwise the filter would be resolved the first time around.
--- kernel/seccomp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
kernel/seccomp.c +1 -4
@@ -1318,11 +1318,8 @@ static int __seccomp_filter(int this_syscall, const bool recheck_after_trace)*/ if (fatal_signal_pending (current)) goto skip; -/* Check if the tracer forced the syscall to be skipped. */ - this_syscall =syscall_get_nr (current,current_pt_regs ()); -if (this_syscall <0 ) - goto skip; + this_syscall =syscall_get_nr (current,current_pt_regs ());/* * Recheck the syscall, since it may have changed. This * intentionally uses a NULL struct seccomp_data to force
Signature · 1 line
2.51.0
[email protected]
AI reviewRe: [PATCH] seccomp: Fix syscall skip logic on ptrace
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Critical] Removing the explicit check for tracer-injected negative syscall numbers breaks ptrace syscall…
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] Removing the explicit check for tracer-injected negative syscall numbers breaks ptrace syscall emulation by erroneously re-evaluating the seccomp BPF filter against a -1 syscall number. --
--- Patch [1]: [PATCH] seccomp: Fix syscall skip logic on ptrace --- commit e1c90f3fd79c2a1c1deae6adb363b4de34006c48
Author: Michal Suchanek <[email protected]>
seccomp: Fix syscall skip logic on ptrace
This commit removes the explicit check for negative syscall numbers after a ptrace stop in the seccomp filter. This allows architectures where the return value overlaps with the syscall number or arguments to exit without flagging the syscall as skipped.
Quoted 5 lines
kernel/seccomp.c +0
-0
kernel/seccomp.c static int __seccomp_filter(int this_syscall, const bool recheck_after_trace) · line 1322
Quoted 9 lines
kernel/seccomp.c +1
-4@@ -1318,11 +1318,8 @@ static int __seccomp_filter(int this_syscall, const bool recheck_after_trace)*/ if (fatal_signal_pending (current)) goto skip; -/* Check if the tracer forced the syscall to be skipped. */ - this_syscall =syscall_get_nr (current,current_pt_regs ()); -if (this_syscall <0 ) - goto skip; + this_syscall =syscall_get_nr (current,current_pt_regs ());
[Severity: Critical]
By removing this check, does this break ptrace syscall emulation?
The standard mechanism for syscall emulation using ptrace and seccomp (used by gVisor, User-Mode Linux, proot, and strace) involves changing the syscall number to -1 to skip the real kernel syscall and setting a custom return value.
Without this check, when the tracee resumes and re-enters __seccomp_filter(), the -1 syscall number will fall through to the BPF evaluation below. Since most seccomp profiles use strict allowlists, won't this cause the -1 syscall to hit the default action (like SECCOMP_RET_KILL_PROCESS or SECCOMP_RET_ERRNO) instead of skipping it?
Could this lead to tracees being unexpectedly killed or having their preset return values overwritten?
Quoted 3 lines
kernel/seccomp.c +0
-0/* * Recheck the syscall, since it may have changed. This * intentionally uses a NULL struct seccomp_data to force
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Kees Cook
maintainerRe: [PATCH] seccomp: Fix syscall skip logic on ptrace
In reply to Michal SuchanekQuoted 35 lines · Michal Suchanek
seccomp takes a shortcut here. When the syscall number is re-read after ptrace and the sign bit is set in the syscall number the syscall is skipped right away.
This works fairly well on x86 where the return value of the syscall is preset before seccomp is processed.
However, on some architectures the syscall return value overlaps with the syscall number or syscall arguments, and as a result the return value cannot be preset in advance.
For these architectures seccomp needs to exit without flagging the syscall as skipped. Then processing of invalid syscall number in the architecture code should set the return value to
-ENOSYSand skip the syscall.This introduces a change: If the syscall number has the sign bit set, such as -1, previously the filter re-check would not be done, not applying the filter after trace. Now the re-check is done both for syscall nubers with and without sign bit set. This would only make a difference if the syscall number or the filter was changed by the tracer. Otherwise the filter would be resolved the first time around.
Signed-off-by Michal Suchanek <[email protected]>--- kernel/seccomp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)kernel/seccomp.c +0
-0@@ -1318,11 +1318,8 @@ static int __seccomp_filter(int this_syscall, const bool recheck_after_trace)*/ if (fatal_signal_pending (current))
kernel/seccomp.c static int __seccomp_filter(int this_syscall, const bool recheck_after_trace) · line 1325
Quoted 10 lines
kernel/seccomp.c +1
-4goto skip; -/* Check if the tracer forced the syscall to be skipped. */ - this_syscall =syscall_get_nr (current,current_pt_regs ()); -if (this_syscall <0 ) - goto skip; + this_syscall =syscall_get_nr (current,current_pt_regs ());/* * Recheck the syscall, since it may have changed. This * intentionally uses a NULL struct seccomp_data to force
Does the seccomp selftest still pass with this change? I _think_ it's fine; this just induces more work on a tracer-induced skip path, which, in theory, shouldn't be fast-path: kicking out to the tracer is going to be the slowest part.
Signature · 1 line
Kees Cook
Re: [PATCH] seccomp: Fix syscall skip logic on ptrace
Quoted 42 lines · Kees Cook
Quoted 41 lines · Michal Suchanek
seccomp takes a shortcut here. When the syscall number is re-read after ptrace and the sign bit is set in the syscall number the syscall is skipped right away.
This works fairly well on x86 where the return value of the syscall is preset before seccomp is processed.
However, on some architectures the syscall return value overlaps with the syscall number or syscall arguments, and as a result the return value cannot be preset in advance.
For these architectures seccomp needs to exit without flagging the syscall as skipped. Then processing of invalid syscall number in the architecture code should set the return value to
-ENOSYSand skip the syscall.This introduces a change: If the syscall number has the sign bit set, such as -1, previously the filter re-check would not be done, not applying the filter after trace. Now the re-check is done both for syscall nubers with and without sign bit set. This would only make a difference if the syscall number or the filter was changed by the tracer. Otherwise the filter would be resolved the first time around.
Signed-off-by Michal Suchanek <[email protected]>--- kernel/seccomp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)kernel/seccomp.c +0
-4@@ -1318,11 +1318,8 @@ static int __seccomp_filter(int this_syscall, const bool recheck_after_trace)*/ if (fatal_signal_pending (current)) goto skip; -/* Check if the tracer forced the syscall to be skipped. */ - this_syscall =syscall_get_nr (current,current_pt_regs ()); -if (this_syscall <0 ) - goto skip;
Quoted 9 lines
kernel/seccomp.c static int __seccomp_filter(int this_syscall, const bool recheck_after_trace) · line 1325
Quoted 4 lines
kernel/seccomp.c +1
-0+ this_syscall =syscall_get_nr (current,current_pt_regs ());/* * Recheck the syscall, since it may have changed. This * intentionally uses a NULL struct seccomp_data to force Does the seccomp selftest still pass with this change? I _think_ it's fine; this just induces more work on a tracer-induced skip path, which, in theory, shouldn't be fast-path: kicking out to the tracer is going to be the slowest part.
It does not pass without this change, either.
On 7.3-rc6 I get:
./seccomp_bpf
TAP version 13
1..111
# Starting 111 tests from 11 test cases.
# RUN global.kcmp ...
# OK global.kcmp
ok 1 global.kcmp
# RUN global.mode_strict_support ...
# OK global.mode_strict_support
ok 2 global.mode_strict_support
# RUN global.mode_strict_cannot_call_prctl ...
# OK global.mode_strict_cannot_call_prctl
ok 3 global.mode_strict_cannot_call_prctl
# RUN global.no_new_privs_support ...
# OK global.no_new_privs_support
ok 4 global.no_new_privs_support
# RUN global.mode_filter_support ...
# OK global.mode_filter_support
ok 5 global.mode_filter_support
# RUN global.mode_filter_without_nnp ...
# OK global.mode_filter_without_nnp
ok 6 global.mode_filter_without_nnp
# RUN global.filter_size_limits ...
# OK global.filter_size_limits
ok 7 global.filter_size_limits
# RUN global.filter_chain_limits ...
# OK global.filter_chain_limits
ok 8 global.filter_chain_limits
# RUN global.mode_filter_cannot_move_to_strict ...
# OK global.mode_filter_cannot_move_to_strict
ok 9 global.mode_filter_cannot_move_to_strict
# RUN global.mode_filter_get_seccomp ...
# OK global.mode_filter_get_seccomp
ok 10 global.mode_filter_get_seccomp
# RUN global.ALLOW_all ...
# OK global.ALLOW_all
ok 11 global.ALLOW_all
# RUN global.empty_prog ...
# OK global.empty_prog
ok 12 global.empty_prog
# RUN global.log_all ...
# OK global.log_all
ok 13 global.log_all
# RUN global.unknown_ret_is_kill_inside ...
# OK global.unknown_ret_is_kill_inside
ok 14 global.unknown_ret_is_kill_inside
# RUN global.unknown_ret_is_kill_above_allow ...
# OK global.unknown_ret_is_kill_above_allow
ok 15 global.unknown_ret_is_kill_above_allow
# RUN global.KILL_all ...
# OK global.KILL_all
ok 16 global.KILL_all
# RUN global.KILL_one ...
# OK global.KILL_one
ok 17 global.KILL_one
# RUN global.KILL_one_arg_one ...
# OK global.KILL_one_arg_one
ok 18 global.KILL_one_arg_one
# RUN global.KILL_one_arg_six ...
# OK global.KILL_one_arg_six
ok 19 global.KILL_one_arg_six
# RUN global.KILL_thread ...
# OK global.KILL_thread
ok 20 global.KILL_thread
# RUN global.KILL_process ...
# OK global.KILL_process
ok 21 global.KILL_process
# RUN global.KILL_unknown ...
# OK global.KILL_unknown
ok 22 global.KILL_unknown
# RUN global.arg_out_of_range ...
# OK global.arg_out_of_range
ok 23 global.arg_out_of_range
# RUN global.ERRNO_valid ...
# OK global.ERRNO_valid
ok 24 global.ERRNO_valid
# RUN global.ERRNO_zero ...
# OK global.ERRNO_zero
ok 25 global.ERRNO_zero
# RUN global.ERRNO_capped ...
# OK global.ERRNO_capped
ok 26 global.ERRNO_capped
# RUN global.ERRNO_order ...
# OK global.ERRNO_order
ok 27 global.ERRNO_order
# RUN global.negative_ENOSYS ...
# OK global.negative_ENOSYS
ok 28 global.negative_ENOSYS
# RUN global.seccomp_syscall ...
# OK global.seccomp_syscall
ok 29 global.seccomp_syscall
# RUN global.seccomp_syscall_mode_lock ...
# OK global.seccomp_syscall_mode_lock
ok 30 global.seccomp_syscall_mode_lock
# RUN global.detect_seccomp_filter_flags ...
# OK global.detect_seccomp_filter_flags
ok 31 global.detect_seccomp_filter_flags
# RUN global.TSYNC_first ...
# OK global.TSYNC_first
ok 32 global.TSYNC_first
# RUN global.syscall_restart ...
# OK global.syscall_restart
ok 33 global.syscall_restart
# RUN global.filter_flag_log ...
# OK global.filter_flag_log
ok 34 global.filter_flag_log
# RUN global.get_action_avail ...
# OK global.get_action_avail
ok 35 global.get_action_avail
# RUN global.get_metadata ...
# OK global.get_metadata
ok 36 global.get_metadata
# RUN global.user_notification_basic ...
# seccomp_bpf.c:3488:user_notification_basic:Expected 0 (0) == WEXITSTATUS(status) (1) # user_notification_basic: Test failed
# FAIL global.user_notification_basic
not ok 37 global.user_notification_basic
# RUN global.user_notification_with_tsync ...
# OK global.user_notification_with_tsync
ok 38 global.user_notification_with_tsync
# RUN global.user_notification_kill_in_middle ...
# OK global.user_notification_kill_in_middle
ok 39 global.user_notification_kill_in_middle
# RUN global.user_notification_signal ...
# OK global.user_notification_signal
ok 40 global.user_notification_signal
# RUN global.user_notification_closed_listener ...
# OK global.user_notification_closed_listener
ok 41 global.user_notification_closed_listener
# RUN global.user_notification_child_pid_ns ...
# seccomp_bpf.c:3713:user_notification_child_pid_ns:Expected 0 (0) == WEXITSTATUS(status) (1) # user_notification_child_pid_ns: Test failed
# FAIL global.user_notification_child_pid_ns
not ok 42 global.user_notification_child_pid_ns
# RUN global.user_notification_sibling_pid_ns ...
# seccomp_bpf.c:3755:user_notification_sibling_pid_ns:Expected 0 (0) == WEXITSTATUS(status) (1) # seccomp_bpf.c:3791:user_notification_sibling_pid_ns:Expected 0 (0) == WEXITSTATUS(status) (1) # user_notification_sibling_pid_ns: Test failed
# FAIL global.user_notification_sibling_pid_ns
not ok 43 global.user_notification_sibling_pid_ns
# RUN global.user_notification_fault_recv ...
# seccomp_bpf.c:3836:user_notification_fault_recv:Expected 0 (0) == WEXITSTATUS(status) (1) # user_notification_fault_recv: Test failed
# FAIL global.user_notification_fault_recv
not ok 44 global.user_notification_fault_recv
# RUN global.seccomp_get_notif_sizes ...
# OK global.seccomp_get_notif_sizes
ok 45 global.seccomp_get_notif_sizes
# RUN global.user_notification_continue ...
# OK global.user_notification_continue
ok 46 global.user_notification_continue
# RUN global.user_notification_filter_empty ...
# OK global.user_notification_filter_empty
ok 47 global.user_notification_filter_empty
# RUN global.user_ioctl_notification_filter_empty ...
# OK global.user_ioctl_notification_filter_empty
ok 48 global.user_ioctl_notification_filter_empty
# RUN global.user_notification_filter_empty_threaded ...
# OK global.user_notification_filter_empty_threaded
ok 49 global.user_notification_filter_empty_threaded
# RUN global.user_notification_addfd ...
# user_notification_addfd: Test terminated by timeout
# FAIL global.user_notification_addfd
not ok 50 global.user_notification_addfd
# RUN global.user_notification_addfd_rlimit ...
# seccomp_bpf.c:4366:user_notification_addfd_rlimit:Expected 0 (0) == WEXITSTATUS(status) (1) # user_notification_addfd_rlimit: Test failed
# FAIL global.user_notification_addfd_rlimit
not ok 51 global.user_notification_addfd_rlimit
# RUN global.user_notification_sync ...
# seccomp_bpf.c:4404:user_notification_sync:Expected ret (0) == USER_NOTIF_MAGIC (2147483647) # seccomp_bpf.c:4422:user_notification_sync:Expected status (256) == 0 (0)
# user_notification_sync: Test terminated by assertion
# FAIL global.user_notification_sync
not ok 52 global.user_notification_sync
# RUN global.user_notification_fifo ...
# seccomp_bpf.c:4581:user_notification_fifo:Expected 0 (0) == WEXITSTATUS(status) (1) # seccomp_bpf.c:4615:user_notification_fifo:Expected 0 (0) == WEXITSTATUS(status) (1) # seccomp_bpf.c:4615:user_notification_fifo:Expected 0 (0) == WEXITSTATUS(status) (1) # seccomp_bpf.c:4615:user_notification_fifo:Expected 0 (0) == WEXITSTATUS(status) (1) # user_notification_fifo: Test failed
# FAIL global.user_notification_fifo
not ok 53 global.user_notification_fifo
# RUN global.user_notification_wait_killable_pre_notification ...
# OK global.user_notification_wait_killable_pre_notification
ok 54 global.user_notification_wait_killable_pre_notification
# RUN global.user_notification_wait_killable ...
# seccomp_bpf.c:4788:user_notification_wait_killable:Expected 0 (0) == WEXITSTATUS(status) (1) # user_notification_wait_killable: Test failed
# FAIL global.user_notification_wait_killable
not ok 55 global.user_notification_wait_killable
# RUN global.user_notification_wait_killable_fatal ...
# OK global.user_notification_wait_killable_fatal
ok 56 global.user_notification_wait_killable_fatal
# RUN global.user_notification_wait_killable_after_reply ...
# OK global.user_notification_wait_killable_after_reply
ok 57 global.user_notification_wait_killable_after_reply
# RUN global.tsync_vs_dead_thread_leader ...
# OK global.tsync_vs_dead_thread_leader
ok 58 global.tsync_vs_dead_thread_leader
# RUN TRAP.dfl ...
# OK TRAP.dfl
ok 59 TRAP.dfl
# RUN TRAP.ign ...
# OK TRAP.ign
ok 60 TRAP.ign
# RUN TRAP.handler ...
# OK TRAP.handler
ok 61 TRAP.handler
# RUN precedence.allow_ok ...
# OK precedence.allow_ok
ok 62 precedence.allow_ok
# RUN precedence.kill_is_highest ...
# OK precedence.kill_is_highest
ok 63 precedence.kill_is_highest
# RUN precedence.kill_is_highest_in_any_order ...
# OK precedence.kill_is_highest_in_any_order
ok 64 precedence.kill_is_highest_in_any_order
# RUN precedence.trap_is_second ...
# OK precedence.trap_is_second
ok 65 precedence.trap_is_second
# RUN precedence.trap_is_second_in_any_order ...
# OK precedence.trap_is_second_in_any_order
ok 66 precedence.trap_is_second_in_any_order
# RUN precedence.errno_is_third ...
# OK precedence.errno_is_third
ok 67 precedence.errno_is_third
# RUN precedence.errno_is_third_in_any_order ...
# OK precedence.errno_is_third_in_any_order
ok 68 precedence.errno_is_third_in_any_order
# RUN precedence.trace_is_fourth ...
# OK precedence.trace_is_fourth
ok 69 precedence.trace_is_fourth
# RUN precedence.trace_is_fourth_in_any_order ...
# OK precedence.trace_is_fourth_in_any_order
ok 70 precedence.trace_is_fourth_in_any_order
# RUN precedence.log_is_fifth ...
# OK precedence.log_is_fifth
ok 71 precedence.log_is_fifth
# RUN precedence.log_is_fifth_in_any_order ...
# OK precedence.log_is_fifth_in_any_order
ok 72 precedence.log_is_fifth_in_any_order
# RUN TRACE_poke.read_has_side_effects ...
# OK TRACE_poke.read_has_side_effects
ok 73 TRACE_poke.read_has_side_effects
# RUN TRACE_poke.getpid_runs_normally ...
# OK TRACE_poke.getpid_runs_normally
ok 74 TRACE_poke.getpid_runs_normally
# RUN TRACE_syscall.ptrace.negative_ENOSYS ...
# OK TRACE_syscall.ptrace.negative_ENOSYS
ok 75 TRACE_syscall.ptrace.negative_ENOSYS
# RUN TRACE_syscall.ptrace.syscall_allowed ...
# OK TRACE_syscall.ptrace.syscall_allowed
ok 76 TRACE_syscall.ptrace.syscall_allowed
# RUN TRACE_syscall.ptrace.syscall_redirected ...
# OK TRACE_syscall.ptrace.syscall_redirected
ok 77 TRACE_syscall.ptrace.syscall_redirected
# RUN TRACE_syscall.ptrace.syscall_errno ...
# OK TRACE_syscall.ptrace.syscall_errno
ok 78 TRACE_syscall.ptrace.syscall_errno
# RUN TRACE_syscall.ptrace.syscall_faked ...
# OK TRACE_syscall.ptrace.syscall_faked
ok 79 TRACE_syscall.ptrace.syscall_faked
# RUN TRACE_syscall.ptrace.kill_immediate ...
# OK TRACE_syscall.ptrace.kill_immediate
ok 80 TRACE_syscall.ptrace.kill_immediate
# RUN TRACE_syscall.ptrace.skip_after ...
# OK TRACE_syscall.ptrace.skip_after
ok 81 TRACE_syscall.ptrace.skip_after
# RUN TRACE_syscall.ptrace.kill_after ...
# OK TRACE_syscall.ptrace.kill_after
ok 82 TRACE_syscall.ptrace.kill_after
# RUN TRACE_syscall.seccomp.negative_ENOSYS ...
# OK TRACE_syscall.seccomp.negative_ENOSYS
ok 83 TRACE_syscall.seccomp.negative_ENOSYS
# RUN TRACE_syscall.seccomp.syscall_allowed ...
# OK TRACE_syscall.seccomp.syscall_allowed
ok 84 TRACE_syscall.seccomp.syscall_allowed
# RUN TRACE_syscall.seccomp.syscall_redirected ...
# OK TRACE_syscall.seccomp.syscall_redirected
ok 85 TRACE_syscall.seccomp.syscall_redirected
# RUN TRACE_syscall.seccomp.syscall_errno ...
# OK TRACE_syscall.seccomp.syscall_errno
ok 86 TRACE_syscall.seccomp.syscall_errno
# RUN TRACE_syscall.seccomp.syscall_faked ...
# seccomp_bpf.c:2253:syscall_faked:Expected 45000 (45000) == syscall(207) (0)
# syscall_faked: Test failed
# FAIL TRACE_syscall.seccomp.syscall_faked
not ok 87 TRACE_syscall.seccomp.syscall_faked
# RUN TRACE_syscall.seccomp.kill_immediate ...
# OK TRACE_syscall.seccomp.kill_immediate
ok 88 TRACE_syscall.seccomp.kill_immediate
# RUN TRACE_syscall.seccomp.skip_after ...
# OK TRACE_syscall.seccomp.skip_after
ok 89 TRACE_syscall.seccomp.skip_after
# RUN TRACE_syscall.seccomp.kill_after ...
# OK TRACE_syscall.seccomp.kill_after
ok 90 TRACE_syscall.seccomp.kill_after
# RUN TSYNC.siblings_fail_prctl ...
# OK TSYNC.siblings_fail_prctl
ok 91 TSYNC.siblings_fail_prctl
# RUN TSYNC.two_siblings_with_ancestor ...
# OK TSYNC.two_siblings_with_ancestor
ok 92 TSYNC.two_siblings_with_ancestor
# RUN TSYNC.two_sibling_want_nnp ...
# OK TSYNC.two_sibling_want_nnp
ok 93 TSYNC.two_sibling_want_nnp
# RUN TSYNC.two_siblings_with_no_filter ...
# OK TSYNC.two_siblings_with_no_filter
ok 94 TSYNC.two_siblings_with_no_filter
# RUN TSYNC.two_siblings_with_one_divergence ...
# OK TSYNC.two_siblings_with_one_divergence
ok 95 TSYNC.two_siblings_with_one_divergence
# RUN TSYNC.two_siblings_with_one_divergence_no_tid_in_err ...
# OK TSYNC.two_siblings_with_one_divergence_no_tid_in_err
ok 96 TSYNC.two_siblings_with_one_divergence_no_tid_in_err
# RUN TSYNC.two_siblings_not_under_filter ...
# OK TSYNC.two_siblings_not_under_filter
ok 97 TSYNC.two_siblings_not_under_filter
# RUN O_SUSPEND_SECCOMP.setoptions ...
# OK O_SUSPEND_SECCOMP.setoptions
ok 98 O_SUSPEND_SECCOMP.setoptions
# RUN O_SUSPEND_SECCOMP.seize ...
# OK O_SUSPEND_SECCOMP.seize
ok 99 O_SUSPEND_SECCOMP.seize
# RUN UPROBE.not_attached.uprobe_default_allow ... # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # OK UPROBE.not_attached.uprobe_default_allow ok 100 UPROBE.not_attached.uprobe_default_allow # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # RUN UPROBE.not_attached.uprobe_default_block ... # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # OK UPROBE.not_attached.uprobe_default_block ok 101 UPROBE.not_attached.uprobe_default_block # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # RUN UPROBE.not_attached.uprobe_block_syscall ... # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # OK UPROBE.not_attached.uprobe_block_syscall ok 102 UPROBE.not_attached.uprobe_block_syscall # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # RUN UPROBE.not_attached.uprobe_default_block_with_syscall ... # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # OK UPROBE.not_attached.uprobe_default_block_with_syscall ok 103 UPROBE.not_attached.uprobe_default_block_with_syscall # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # RUN UPROBE.uprobe_attached.uprobe_default_allow ... # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # OK UPROBE.uprobe_attached.uprobe_default_allow ok 104 UPROBE.uprobe_attached.uprobe_default_allow # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # RUN UPROBE.uprobe_attached.uprobe_default_block ... # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # OK UPROBE.uprobe_attached.uprobe_default_block ok 105 UPROBE.uprobe_attached.uprobe_default_block # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # RUN UPROBE.uprobe_attached.uprobe_block_syscall ... # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # OK UPROBE.uprobe_attached.uprobe_block_syscall ok 106 UPROBE.uprobe_attached.uprobe_block_syscall # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # RUN UPROBE.uprobe_attached.uprobe_default_block_with_syscall ... # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # OK UPROBE.uprobe_attached.uprobe_default_block_with_syscall ok 107 UPROBE.uprobe_attached.uprobe_default_block_with_syscall # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # RUN UPROBE.uretprobe_attached.uprobe_default_allow ... # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # OK UPROBE.uretprobe_attached.uprobe_default_allow ok 108 UPROBE.uretprobe_attached.uprobe_default_allow # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # RUN UPROBE.uretprobe_attached.uprobe_default_block ... # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # OK UPROBE.uretprobe_attached.uprobe_default_block ok 109 UPROBE.uretprobe_attached.uprobe_default_block # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # RUN UPROBE.uretprobe_attached.uprobe_block_syscall ... # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # OK UPROBE.uretprobe_attached.uprobe_block_syscall ok 110 UPROBE.uretprobe_attached.uprobe_block_syscall # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # RUN UPROBE.uretprobe_attached.uprobe_default_block_with_syscall ... # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # OK UPROBE.uretprobe_attached.uprobe_default_block_with_syscall
ok 111 UPROBE.uretprobe_attached.uprobe_default_block_with_syscall # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # FAILED: 101 / 111 tests passed.
# 12 skipped test(s) detected. Consider enabling relevant config options to improve coverage.
# Totals: pass:89 fail:10 xfail:0 xpass:0 skip:12 error:0
but it does have an additional failure:
test-patched.log renamed from test-base.log +7 -5
@@ -279,10 +279,12 @@ # OK TRACE_syscall.seccomp.syscall_redirected ok 85 TRACE_syscall.seccomp.syscall_redirected # RUN TRACE_syscall.seccomp.syscall_errno ... -# OK TRACE_syscall.seccomp.syscall_errno -ok 86 TRACE_syscall.seccomp.syscall_errno +# seccomp_bpf.c:2247:syscall_errno:Expected -(-3) (3) == errno (38) +# syscall_errno: Test failed +# FAIL TRACE_syscall.seccomp.syscall_errno +not ok 86 TRACE_syscall.seccomp.syscall_errno # RUN TRACE_syscall.seccomp.syscall_faked ... -# seccomp_bpf.c:2253:syscall_faked:Expected 45000 (45000) == syscall(207) (0) +# seccomp_bpf.c:2253:syscall_faked:Expected 45000 (45000) == syscall(207) (-1) # syscall_faked: Test failed # FAIL TRACE_syscall.seccomp.syscall_faked not ok 87 TRACE_syscall.seccomp.syscall_faked
@@ -370,6 +372,6 @@ # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined # OK UPROBE.uretprobe_attached.uprobe_default_block_with_syscall ok 111 UPROBE.uretprobe_attached.uprobe_default_block_with_syscall # SKIP __NR_uprobe ot __NR_uretprobe syscalls not defined -# FAILED: 101 / 111 tests passed. +# FAILED: 100 / 111 tests passed. # 12 skipped test(s) detected. Consider enabling relevant config options to improve coverage. -# Totals: pass:89 fail:10 xfail:0 xpass:0 skip:12 error:0 +# Totals: pass:88 fail:11 xfail:0 xpass:0 skip:12 error:0
Thanks
Michal