Skip to content

entry: Consolidate and rework syscall entry handling

Thomas Gleixner linux-alpha linux-arch linux-csky linux-doc linux-hexagon linux-m68k linux-mips linux-parisc linux-riscv linux-s390 linux-sh linux-snps-arc linux-um linuxppc-dev lkml loongarch openrisc sashiko-reviews sparclinux stable 1 version Applied

Status from this message: The following commit has been merged into the core/entry branch of tip:

Get series with b4
b4 am [email protected]

Versions newest first

  1. v1 Latest18 patches 100 repliesApplied

Patches in v1 Applied

#Subject and filesSizeRepliesApplied
1/18powerpc: Move stack randomization after syscall_enter_from_user_mode()arch/powerpc/kernel/syscall.c+1 -15 replies
2/18randomize_kstack: Provide add_random_kstack_offset_irqsoff()include/linux/randomize_kstack.h+19 -04 replies
3/18entry: Provide [syscall_]enter_from_user_mode_randomize_stack()include/linux/entry-common.h+56 -07 replies
4/18loongarch/syscall: Use syscall_enter_from_user_mode_randomize_stack()arch/loongarch/kernel/syscall.c+1 -44 replies
5/18powerpc/syscall: Use syscall_enter_from_user_mode_randomize_stack()arch/powerpc/kernel/syscall.c+1 -34 replies
6/18riscv/syscall: Use syscall_enter_from_user_mode_randomize_stack()arch/riscv/kernel/traps.c+1 -45 replies
7/18s390/syscall: Use enter_from_user_mode_randomize_stack()arch/s390/kernel/syscall.c+2 -26 replies
8/18x86/syscall: Use [syscall_]enter_from_user_mode_randomize_stack()arch/x86/entry/syscall_32.c arch/x86/entry/syscall_64.c arch/x86/include/asm/entry-common.h+6 -174 replies
9/18entry: Remove syscall_enter_from_user_mode()Documentation/core-api/entry.rst include/linux/entry-common.h include/linux/irq-entry-common.h+17 -464 replies
10/18entry: Use syscall number instead of rereading itinclude/linux/entry-common.h+5 -45 replies
11/18seccomp, treewide: Rename and convert __secure_computing() to return booleanarch/alpha/kernel/ptrace.c arch/arm/kernel/ptrace.c arch/arm64/kernel/ptrace.c +11 more+45 -466 replies
12/18ptrace, treewide: Rename ptrace_report_syscall_entry() to ptrace_report_syscall_permit_entry()arch/alpha/kernel/ptrace.c arch/arc/kernel/ptrace.c arch/arm/kernel/ptrace.c +17 more+40 -447 replies
13/18entry: Make trace_syscall_enter() return type boolinclude/linux/entry-common.h kernel/entry/syscall-common.c+9 -611 replies
14/18entry: Make return type of syscall_trace_enter() boolinclude/linux/entry-common.h+15 -131 reply
15/18x86/entry: Make syscall functions staticarch/x86/entry/syscall_32.c arch/x86/entry/syscall_64.c arch/x86/include/asm/syscall.h+7 -132 replies
16/18x86/entry: Get rid of the sys_ni_syscall() indirectionarch/x86/entry/syscall_32.c arch/x86/entry/syscall_64.c+3 -917 replies
17/18x86/entry: Simplify the syscall number logicarch/x86/entry/syscall_32.c arch/x86/entry/syscall_64.c arch/x86/include/asm/syscall.h+26 -380 replies
18/18entry, treewide: Make syscall_enter_from_user_mode[_work]() indicate syscall executionDocumentation/core-api/entry.rst arch/loongarch/kernel/syscall.c arch/powerpc/kernel/syscall.c +5 more+53 -493 replies

Reviews trailers per patch

16 of 18 patches have a Reviewed-by or Acked-by of their own; the series has one for all of them.

PatchJinjie RuanSven SchnelleShrikanth HegdeOleg NesterovRadu RendecGeert UytterhoevenPhilippe Mathieu-DaudéKees CookMukesh Kumar Chaurasiya (IBM)Magnus LindholmGuo RenSebastian Andrzej Siewior
SeriesT-b A-b T-b
1/18R-b R-b R-b R-b R-b
2/18R-b R-b R-b
3/18R-b R-b R-b R-b
4/18R-b R-b R-b R-b
5/18R-b R-b R-b R-b
6/18R-b R-b R-b R-b R-b
7/18R-b R-b R-b R-b R-b
8/18R-b R-b R-b R-b
9/18R-b R-b
10/18R-b R-b R-b R-b
11/18R-b A-b R-b
12/18R-b A-b R-b A-b R-b
13/18
14/18R-b
15/18R-b R-b
16/18R-b T-b
17/18
18/18R-b

Trailers given in replies are filled; those carried in the patches from earlier versions are outlined with dashes. Scroll the table sideways for all 12 reviewers.

Read the v1 thread

Cover letter [patch 00/18] 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(-)