x86/syscall: Mark exit[_group] syscall handlers __noreturn
The direct-call syscall dispatch function doesn't know that the exit()
and exit_group() syscall handlers don't return, so the call sites aren't
optimized accordingly.
Fix that by marking the exit syscall declarations __noreturn.
Fixes the following warnings:
vmlinux.o: warning: objtool: x64_sys_call+0x2804: __x64_sys_exit() is missing a __noreturn annotation
vmlinux.o: warning: objtool: ia32_sys_call+0x29b6: __ia32_sys_exit_group() is missing a __noreturn annotation
Fixes: 1e3ad78334
("x86/syscall: Don't force use of indirect calls for system calls")
Closes: https://lkml.kernel.org/lkml/6dba9b32-db2c-4e6d-9500-7a08852f17a3@paulmck-laptop
Reported-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Tested-by: Paul E. McKenney <paulmck@kernel.org>
Link: https://lore.kernel.org/r/5d8882bc077d8eadcc7fd1740b56dfb781f12288.1719381528.git.jpoimboe@kernel.org
This commit is contained in:
parent
f2661062f1
commit
9142be9e64
@ -14,10 +14,13 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define __SYSCALL(nr, sym) extern long __ia32_##sym(const struct pt_regs *);
|
#define __SYSCALL(nr, sym) extern long __ia32_##sym(const struct pt_regs *);
|
||||||
|
#define __SYSCALL_NORETURN(nr, sym) extern long __noreturn __ia32_##sym(const struct pt_regs *);
|
||||||
#include <asm/syscalls_32.h>
|
#include <asm/syscalls_32.h>
|
||||||
#undef __SYSCALL
|
#undef __SYSCALL
|
||||||
|
|
||||||
|
#undef __SYSCALL_NORETURN
|
||||||
|
#define __SYSCALL_NORETURN __SYSCALL
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The sys_call_table[] is no longer used for system calls, but
|
* The sys_call_table[] is no longer used for system calls, but
|
||||||
* kernel/trace/trace_syscalls.c still wants to know the system
|
* kernel/trace/trace_syscalls.c still wants to know the system
|
||||||
@ -32,7 +35,6 @@ const sys_call_ptr_t sys_call_table[] = {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define __SYSCALL(nr, sym) case nr: return __ia32_##sym(regs);
|
#define __SYSCALL(nr, sym) case nr: return __ia32_##sym(regs);
|
||||||
|
|
||||||
long ia32_sys_call(const struct pt_regs *regs, unsigned int nr)
|
long ia32_sys_call(const struct pt_regs *regs, unsigned int nr)
|
||||||
{
|
{
|
||||||
switch (nr) {
|
switch (nr) {
|
||||||
|
@ -8,9 +8,13 @@
|
|||||||
#include <asm/syscall.h>
|
#include <asm/syscall.h>
|
||||||
|
|
||||||
#define __SYSCALL(nr, sym) extern long __x64_##sym(const struct pt_regs *);
|
#define __SYSCALL(nr, sym) extern long __x64_##sym(const struct pt_regs *);
|
||||||
|
#define __SYSCALL_NORETURN(nr, sym) extern long __noreturn __x64_##sym(const struct pt_regs *);
|
||||||
#include <asm/syscalls_64.h>
|
#include <asm/syscalls_64.h>
|
||||||
#undef __SYSCALL
|
#undef __SYSCALL
|
||||||
|
|
||||||
|
#undef __SYSCALL_NORETURN
|
||||||
|
#define __SYSCALL_NORETURN __SYSCALL
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The sys_call_table[] is no longer used for system calls, but
|
* The sys_call_table[] is no longer used for system calls, but
|
||||||
* kernel/trace/trace_syscalls.c still wants to know the system
|
* kernel/trace/trace_syscalls.c still wants to know the system
|
||||||
@ -23,7 +27,6 @@ const sys_call_ptr_t sys_call_table[] = {
|
|||||||
#undef __SYSCALL
|
#undef __SYSCALL
|
||||||
|
|
||||||
#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs);
|
#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs);
|
||||||
|
|
||||||
long x64_sys_call(const struct pt_regs *regs, unsigned int nr)
|
long x64_sys_call(const struct pt_regs *regs, unsigned int nr)
|
||||||
{
|
{
|
||||||
switch (nr) {
|
switch (nr) {
|
||||||
|
@ -8,11 +8,14 @@
|
|||||||
#include <asm/syscall.h>
|
#include <asm/syscall.h>
|
||||||
|
|
||||||
#define __SYSCALL(nr, sym) extern long __x64_##sym(const struct pt_regs *);
|
#define __SYSCALL(nr, sym) extern long __x64_##sym(const struct pt_regs *);
|
||||||
|
#define __SYSCALL_NORETURN(nr, sym) extern long __noreturn __x64_##sym(const struct pt_regs *);
|
||||||
#include <asm/syscalls_x32.h>
|
#include <asm/syscalls_x32.h>
|
||||||
#undef __SYSCALL
|
#undef __SYSCALL
|
||||||
|
|
||||||
#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs);
|
#undef __SYSCALL_NORETURN
|
||||||
|
#define __SYSCALL_NORETURN __SYSCALL
|
||||||
|
|
||||||
|
#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs);
|
||||||
long x32_sys_call(const struct pt_regs *regs, unsigned int nr)
|
long x32_sys_call(const struct pt_regs *regs, unsigned int nr)
|
||||||
{
|
{
|
||||||
switch (nr) {
|
switch (nr) {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# 32-bit system call numbers and entry vectors
|
# 32-bit system call numbers and entry vectors
|
||||||
#
|
#
|
||||||
# The format is:
|
# The format is:
|
||||||
# <number> <abi> <name> <entry point> <compat entry point>
|
# <number> <abi> <name> <entry point> [<compat entry point> [noreturn]]
|
||||||
#
|
#
|
||||||
# The __ia32_sys and __ia32_compat_sys stubs are created on-the-fly for
|
# The __ia32_sys and __ia32_compat_sys stubs are created on-the-fly for
|
||||||
# sys_*() system calls and compat_sys_*() compat system calls if
|
# sys_*() system calls and compat_sys_*() compat system calls if
|
||||||
@ -12,7 +12,7 @@
|
|||||||
# The abi is always "i386" for this file.
|
# The abi is always "i386" for this file.
|
||||||
#
|
#
|
||||||
0 i386 restart_syscall sys_restart_syscall
|
0 i386 restart_syscall sys_restart_syscall
|
||||||
1 i386 exit sys_exit
|
1 i386 exit sys_exit - noreturn
|
||||||
2 i386 fork sys_fork
|
2 i386 fork sys_fork
|
||||||
3 i386 read sys_read
|
3 i386 read sys_read
|
||||||
4 i386 write sys_write
|
4 i386 write sys_write
|
||||||
@ -263,7 +263,7 @@
|
|||||||
249 i386 io_cancel sys_io_cancel
|
249 i386 io_cancel sys_io_cancel
|
||||||
250 i386 fadvise64 sys_ia32_fadvise64
|
250 i386 fadvise64 sys_ia32_fadvise64
|
||||||
# 251 is available for reuse (was briefly sys_set_zone_reclaim)
|
# 251 is available for reuse (was briefly sys_set_zone_reclaim)
|
||||||
252 i386 exit_group sys_exit_group
|
252 i386 exit_group sys_exit_group - noreturn
|
||||||
253 i386 lookup_dcookie
|
253 i386 lookup_dcookie
|
||||||
254 i386 epoll_create sys_epoll_create
|
254 i386 epoll_create sys_epoll_create
|
||||||
255 i386 epoll_ctl sys_epoll_ctl
|
255 i386 epoll_ctl sys_epoll_ctl
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# 64-bit system call numbers and entry vectors
|
# 64-bit system call numbers and entry vectors
|
||||||
#
|
#
|
||||||
# The format is:
|
# The format is:
|
||||||
# <number> <abi> <name> <entry point>
|
# <number> <abi> <name> <entry point> [<compat entry point> [noreturn]]
|
||||||
#
|
#
|
||||||
# The __x64_sys_*() stubs are created on-the-fly for sys_*() system calls
|
# The __x64_sys_*() stubs are created on-the-fly for sys_*() system calls
|
||||||
#
|
#
|
||||||
@ -68,7 +68,7 @@
|
|||||||
57 common fork sys_fork
|
57 common fork sys_fork
|
||||||
58 common vfork sys_vfork
|
58 common vfork sys_vfork
|
||||||
59 64 execve sys_execve
|
59 64 execve sys_execve
|
||||||
60 common exit sys_exit
|
60 common exit sys_exit - noreturn
|
||||||
61 common wait4 sys_wait4
|
61 common wait4 sys_wait4
|
||||||
62 common kill sys_kill
|
62 common kill sys_kill
|
||||||
63 common uname sys_newuname
|
63 common uname sys_newuname
|
||||||
@ -239,7 +239,7 @@
|
|||||||
228 common clock_gettime sys_clock_gettime
|
228 common clock_gettime sys_clock_gettime
|
||||||
229 common clock_getres sys_clock_getres
|
229 common clock_getres sys_clock_getres
|
||||||
230 common clock_nanosleep sys_clock_nanosleep
|
230 common clock_nanosleep sys_clock_nanosleep
|
||||||
231 common exit_group sys_exit_group
|
231 common exit_group sys_exit_group - noreturn
|
||||||
232 common epoll_wait sys_epoll_wait
|
232 common epoll_wait sys_epoll_wait
|
||||||
233 common epoll_ctl sys_epoll_ctl
|
233 common epoll_ctl sys_epoll_ctl
|
||||||
234 common tgkill sys_tgkill
|
234 common tgkill sys_tgkill
|
||||||
|
@ -9,6 +9,10 @@
|
|||||||
#include <linux/cache.h>
|
#include <linux/cache.h>
|
||||||
#include <asm/syscall.h>
|
#include <asm/syscall.h>
|
||||||
|
|
||||||
|
extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long,
|
||||||
|
unsigned long, unsigned long,
|
||||||
|
unsigned long, unsigned long);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Below you can see, in terms of #define's, the differences between the x86-64
|
* Below you can see, in terms of #define's, the differences between the x86-64
|
||||||
* and the UML syscall table.
|
* and the UML syscall table.
|
||||||
@ -22,15 +26,13 @@
|
|||||||
#define sys_vm86 sys_ni_syscall
|
#define sys_vm86 sys_ni_syscall
|
||||||
|
|
||||||
#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)
|
#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)
|
||||||
|
#define __SYSCALL_NORETURN __SYSCALL
|
||||||
|
|
||||||
#define __SYSCALL(nr, sym) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
|
#define __SYSCALL(nr, sym) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
|
||||||
#include <asm/syscalls_32.h>
|
#include <asm/syscalls_32.h>
|
||||||
|
|
||||||
#undef __SYSCALL
|
#undef __SYSCALL
|
||||||
|
|
||||||
#define __SYSCALL(nr, sym) sym,
|
#define __SYSCALL(nr, sym) sym,
|
||||||
|
|
||||||
extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
|
|
||||||
|
|
||||||
const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = {
|
const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = {
|
||||||
#include <asm/syscalls_32.h>
|
#include <asm/syscalls_32.h>
|
||||||
};
|
};
|
||||||
|
@ -9,6 +9,10 @@
|
|||||||
#include <linux/cache.h>
|
#include <linux/cache.h>
|
||||||
#include <asm/syscall.h>
|
#include <asm/syscall.h>
|
||||||
|
|
||||||
|
extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long,
|
||||||
|
unsigned long, unsigned long,
|
||||||
|
unsigned long, unsigned long);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Below you can see, in terms of #define's, the differences between the x86-64
|
* Below you can see, in terms of #define's, the differences between the x86-64
|
||||||
* and the UML syscall table.
|
* and the UML syscall table.
|
||||||
@ -18,14 +22,13 @@
|
|||||||
#define sys_iopl sys_ni_syscall
|
#define sys_iopl sys_ni_syscall
|
||||||
#define sys_ioperm sys_ni_syscall
|
#define sys_ioperm sys_ni_syscall
|
||||||
|
|
||||||
|
#define __SYSCALL_NORETURN __SYSCALL
|
||||||
|
|
||||||
#define __SYSCALL(nr, sym) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
|
#define __SYSCALL(nr, sym) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
|
||||||
#include <asm/syscalls_64.h>
|
#include <asm/syscalls_64.h>
|
||||||
|
|
||||||
#undef __SYSCALL
|
#undef __SYSCALL
|
||||||
|
|
||||||
#define __SYSCALL(nr, sym) sym,
|
#define __SYSCALL(nr, sym) sym,
|
||||||
|
|
||||||
extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
|
|
||||||
|
|
||||||
const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = {
|
const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = {
|
||||||
#include <asm/syscalls_64.h>
|
#include <asm/syscalls_64.h>
|
||||||
};
|
};
|
||||||
|
@ -54,7 +54,7 @@ nxt=0
|
|||||||
|
|
||||||
grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | {
|
grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | {
|
||||||
|
|
||||||
while read nr abi name native compat ; do
|
while read nr abi name native compat noreturn; do
|
||||||
|
|
||||||
if [ $nxt -gt $nr ]; then
|
if [ $nxt -gt $nr ]; then
|
||||||
echo "error: $infile: syscall table is not sorted or duplicates the same syscall number" >&2
|
echo "error: $infile: syscall table is not sorted or duplicates the same syscall number" >&2
|
||||||
@ -66,7 +66,21 @@ grep -E "^[0-9]+[[:space:]]+$abis" "$infile" | {
|
|||||||
nxt=$((nxt + 1))
|
nxt=$((nxt + 1))
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [ "$compat" = "-" ]; then
|
||||||
|
unset compat
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$noreturn" ]; then
|
||||||
|
if [ "$noreturn" != "noreturn" ]; then
|
||||||
|
echo "error: $infile: invalid string \"$noreturn\" in 'noreturn' column"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
if [ -n "$compat" ]; then
|
if [ -n "$compat" ]; then
|
||||||
|
echo "__SYSCALL_COMPAT_NORETURN($nr, $native, $compat)"
|
||||||
|
else
|
||||||
|
echo "__SYSCALL_NORETURN($nr, $native)"
|
||||||
|
fi
|
||||||
|
elif [ -n "$compat" ]; then
|
||||||
echo "__SYSCALL_WITH_COMPAT($nr, $native, $compat)"
|
echo "__SYSCALL_WITH_COMPAT($nr, $native, $compat)"
|
||||||
elif [ -n "$native" ]; then
|
elif [ -n "$native" ]; then
|
||||||
echo "__SYSCALL($nr, $native)"
|
echo "__SYSCALL($nr, $native)"
|
||||||
|
@ -7,12 +7,16 @@
|
|||||||
* Yes, this is unfortunate. A better solution is in the works.
|
* Yes, this is unfortunate. A better solution is in the works.
|
||||||
*/
|
*/
|
||||||
NORETURN(__fortify_panic)
|
NORETURN(__fortify_panic)
|
||||||
|
NORETURN(__ia32_sys_exit)
|
||||||
|
NORETURN(__ia32_sys_exit_group)
|
||||||
NORETURN(__kunit_abort)
|
NORETURN(__kunit_abort)
|
||||||
NORETURN(__module_put_and_kthread_exit)
|
NORETURN(__module_put_and_kthread_exit)
|
||||||
NORETURN(__reiserfs_panic)
|
NORETURN(__reiserfs_panic)
|
||||||
NORETURN(__stack_chk_fail)
|
NORETURN(__stack_chk_fail)
|
||||||
NORETURN(__tdx_hypercall_failed)
|
NORETURN(__tdx_hypercall_failed)
|
||||||
NORETURN(__ubsan_handle_builtin_unreachable)
|
NORETURN(__ubsan_handle_builtin_unreachable)
|
||||||
|
NORETURN(__x64_sys_exit)
|
||||||
|
NORETURN(__x64_sys_exit_group)
|
||||||
NORETURN(arch_cpu_idle_dead)
|
NORETURN(arch_cpu_idle_dead)
|
||||||
NORETURN(bch2_trans_in_restart_error)
|
NORETURN(bch2_trans_in_restart_error)
|
||||||
NORETURN(bch2_trans_restart_error)
|
NORETURN(bch2_trans_restart_error)
|
||||||
|
Loading…
Reference in New Issue
Block a user