- More generalization of entry/exit functionality
- The consolidation work to reclaim TIF flags on x86 and also for non-x86
specific TIF flags which are solely relevant for syscall related work
and have been moved into their own storage space. The x86 specific part
had to be merged in to avoid a major conflict.
- The TIF_NOTIFY_SIGNAL work which replaces the inefficient signal
delivery mode of task work and results in an impressive performance
improvement for io_uring. The non-x86 consolidation of this is going to
come seperate via Jens.
- The selective syscall redirection facility which provides a clean and
efficient way to support the non-Linux syscalls of WINE by catching them
at syscall entry and redirecting them to the user space emulation. This
can be utilized for other purposes as well and has been designed
carefully to avoid overhead for the regular fastpath. This includes the
core changes and the x86 support code.
- Simplification of the context tracking entry/exit handling for the users
of the generic entry code which guarantee the proper ordering and
protection.
- Preparatory changes to make the generic entry code accomodate S390
specific requirements which are mostly related to their syscall restart
mechanism.
-----BEGIN PGP SIGNATURE-----
iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAl/XoPoTHHRnbHhAbGlu
dXRyb25peC5kZQAKCRCmGPVMDXSYoe0tD/4jSKHIogVM9kVpiYfwjDGS1NluaBXn
71ZoASbX9GZebyGandMyF2QP1iJ24ZO0RztBwHEVH6fyomKB2iFNedssCpO9yfWV
3eFRpOvMpbszY2W2bd0QG3GrqaTttjVfB4ahkGLzqeSbchdob6hZpNDYtBZnujA6
GSnrrurfJkCGoQny+yJQYdQJXQU+BIX90B2a2Q+jW123Luy/iHXC1f/krZSA1m14
fC9xYLSUjPphTzh2ZOW+C3DgdjOL5PfAm/6F+DArt4GtLgrEGD7R74aLSFhvetky
dn5QtG+yAsz1i0cc5Wu/JBcT9tOkY92rPYSyLI9bYQUSQ/bMyuprz6oYKj3dubsu
ZSsKPdkNFPIniL4fLdCMWZcIXX5xgnrxKjdgXZXW3gtrcxSns8w8uED3Sh7dgE08
pgIeq67E5g/OB8kJXH1VxdewmeQb9cOmnzzHwNO7TrrGbBKjDTYHNdYOKf1dUTTK
ZX1UjLfGwxTkMYAbQD1k0JGZ2OLRshzSaH5BW/ZKa3bvJW6yYOq+/YT8B8hbJ8U3
vThlO75/55IJxS5r5Y3vZd/IHdsYbPuETD+TA8tNYtPqNZasW8nnk4TYctWqzDuO
/Ka1wvWYid3c6ySznQn4zSyRjr968AfHeZ9YTUMhWufy5waXVmdBMG41u3IKfsVt
osyzNc4EK19/Mg==
=hsjV
-----END PGP SIGNATURE-----
Merge tag 'core-entry-2020-12-14' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull core entry/exit updates from Thomas Gleixner:
"A set of updates for entry/exit handling:
- More generalization of entry/exit functionality
- The consolidation work to reclaim TIF flags on x86 and also for
non-x86 specific TIF flags which are solely relevant for syscall
related work and have been moved into their own storage space. The
x86 specific part had to be merged in to avoid a major conflict.
- The TIF_NOTIFY_SIGNAL work which replaces the inefficient signal
delivery mode of task work and results in an impressive performance
improvement for io_uring. The non-x86 consolidation of this is
going to come seperate via Jens.
- The selective syscall redirection facility which provides a clean
and efficient way to support the non-Linux syscalls of WINE by
catching them at syscall entry and redirecting them to the user
space emulation. This can be utilized for other purposes as well
and has been designed carefully to avoid overhead for the regular
fastpath. This includes the core changes and the x86 support code.
- Simplification of the context tracking entry/exit handling for the
users of the generic entry code which guarantee the proper ordering
and protection.
- Preparatory changes to make the generic entry code accomodate S390
specific requirements which are mostly related to their syscall
restart mechanism"
* tag 'core-entry-2020-12-14' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (36 commits)
entry: Add syscall_exit_to_user_mode_work()
entry: Add exit_to_user_mode() wrapper
entry_Add_enter_from_user_mode_wrapper
entry: Rename exit_to_user_mode()
entry: Rename enter_from_user_mode()
docs: Document Syscall User Dispatch
selftests: Add benchmark for syscall user dispatch
selftests: Add kselftest for syscall user dispatch
entry: Support Syscall User Dispatch on common syscall entry
kernel: Implement selective syscall userspace redirection
signal: Expose SYS_USER_DISPATCH si_code type
x86: vdso: Expose sigreturn address on vdso to the kernel
MAINTAINERS: Add entry for common entry code
entry: Fix boot for !CONFIG_GENERIC_ENTRY
x86: Support HAVE_CONTEXT_TRACKING_OFFSTACK
context_tracking: Only define schedule_user() on !HAVE_CONTEXT_TRACKING_OFFSTACK archs
sched: Detect call to schedule from critical entry code
context_tracking: Don't implement exception_enter/exit() on CONFIG_HAVE_CONTEXT_TRACKING_OFFSTACK
context_tracking: Introduce HAVE_CONTEXT_TRACKING_OFFSTACK
x86: Reclaim unused x86 TI flags
...
176 lines
6.6 KiB
C
176 lines
6.6 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include <linux/compat.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/ptrace.h>
|
|
|
|
/*
|
|
* The compat_siginfo_t structure and handing code is very easy
|
|
* to break in several ways. It must always be updated when new
|
|
* updates are made to the main siginfo_t, and
|
|
* copy_siginfo_to_user32() must be updated when the
|
|
* (arch-independent) copy_siginfo_to_user() is updated.
|
|
*
|
|
* It is also easy to put a new member in the compat_siginfo_t
|
|
* which has implicit alignment which can move internal structure
|
|
* alignment around breaking the ABI. This can happen if you,
|
|
* for instance, put a plain 64-bit value in there.
|
|
*/
|
|
static inline void signal_compat_build_tests(void)
|
|
{
|
|
int _sifields_offset = offsetof(compat_siginfo_t, _sifields);
|
|
|
|
/*
|
|
* If adding a new si_code, there is probably new data in
|
|
* the siginfo. Make sure folks bumping the si_code
|
|
* limits also have to look at this code. Make sure any
|
|
* new fields are handled in copy_siginfo_to_user32()!
|
|
*/
|
|
BUILD_BUG_ON(NSIGILL != 11);
|
|
BUILD_BUG_ON(NSIGFPE != 15);
|
|
BUILD_BUG_ON(NSIGSEGV != 9);
|
|
BUILD_BUG_ON(NSIGBUS != 5);
|
|
BUILD_BUG_ON(NSIGTRAP != 5);
|
|
BUILD_BUG_ON(NSIGCHLD != 6);
|
|
BUILD_BUG_ON(NSIGSYS != 2);
|
|
|
|
/* This is part of the ABI and can never change in size: */
|
|
BUILD_BUG_ON(sizeof(compat_siginfo_t) != 128);
|
|
/*
|
|
* The offsets of all the (unioned) si_fields are fixed
|
|
* in the ABI, of course. Make sure none of them ever
|
|
* move and are always at the beginning:
|
|
*/
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, _sifields) != 3 * sizeof(int));
|
|
#define CHECK_CSI_OFFSET(name) BUILD_BUG_ON(_sifields_offset != offsetof(compat_siginfo_t, _sifields.name))
|
|
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_signo) != 0);
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_errno) != 4);
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_code) != 8);
|
|
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_signo) != 0);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_errno) != 4);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_code) != 8);
|
|
/*
|
|
* Ensure that the size of each si_field never changes.
|
|
* If it does, it is a sign that the
|
|
* copy_siginfo_to_user32() code below needs to updated
|
|
* along with the size in the CHECK_SI_SIZE().
|
|
*
|
|
* We repeat this check for both the generic and compat
|
|
* siginfos.
|
|
*
|
|
* Note: it is OK for these to grow as long as the whole
|
|
* structure stays within the padding size (checked
|
|
* above).
|
|
*/
|
|
#define CHECK_CSI_SIZE(name, size) BUILD_BUG_ON(size != sizeof(((compat_siginfo_t *)0)->_sifields.name))
|
|
#define CHECK_SI_SIZE(name, size) BUILD_BUG_ON(size != sizeof(((siginfo_t *)0)->_sifields.name))
|
|
|
|
CHECK_CSI_OFFSET(_kill);
|
|
CHECK_CSI_SIZE (_kill, 2*sizeof(int));
|
|
CHECK_SI_SIZE (_kill, 2*sizeof(int));
|
|
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_pid) != 0x10);
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_uid) != 0x14);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_pid) != 0xC);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_uid) != 0x10);
|
|
|
|
CHECK_CSI_OFFSET(_timer);
|
|
CHECK_CSI_SIZE (_timer, 3*sizeof(int));
|
|
CHECK_SI_SIZE (_timer, 6*sizeof(int));
|
|
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_tid) != 0x10);
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_overrun) != 0x14);
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_value) != 0x18);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_tid) != 0x0C);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_overrun) != 0x10);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_value) != 0x14);
|
|
|
|
CHECK_CSI_OFFSET(_rt);
|
|
CHECK_CSI_SIZE (_rt, 3*sizeof(int));
|
|
CHECK_SI_SIZE (_rt, 4*sizeof(int));
|
|
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_pid) != 0x10);
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_uid) != 0x14);
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_value) != 0x18);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_pid) != 0x0C);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_uid) != 0x10);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_value) != 0x14);
|
|
|
|
CHECK_CSI_OFFSET(_sigchld);
|
|
CHECK_CSI_SIZE (_sigchld, 5*sizeof(int));
|
|
CHECK_SI_SIZE (_sigchld, 8*sizeof(int));
|
|
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_pid) != 0x10);
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_uid) != 0x14);
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_status) != 0x18);
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_utime) != 0x20);
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_stime) != 0x28);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_pid) != 0x0C);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_uid) != 0x10);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_status) != 0x14);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_utime) != 0x18);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_stime) != 0x1C);
|
|
|
|
#ifdef CONFIG_X86_X32_ABI
|
|
CHECK_CSI_OFFSET(_sigchld_x32);
|
|
CHECK_CSI_SIZE (_sigchld_x32, 7*sizeof(int));
|
|
/* no _sigchld_x32 in the generic siginfo_t */
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, _sifields._sigchld_x32._utime) != 0x18);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, _sifields._sigchld_x32._stime) != 0x20);
|
|
#endif
|
|
|
|
CHECK_CSI_OFFSET(_sigfault);
|
|
CHECK_CSI_SIZE (_sigfault, 4*sizeof(int));
|
|
CHECK_SI_SIZE (_sigfault, 8*sizeof(int));
|
|
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
|
|
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_addr_lsb) != 0x18);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr_lsb) != 0x10);
|
|
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_lower) != 0x20);
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_upper) != 0x28);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_lower) != 0x14);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_upper) != 0x18);
|
|
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_pkey) != 0x20);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_pkey) != 0x14);
|
|
|
|
CHECK_CSI_OFFSET(_sigpoll);
|
|
CHECK_CSI_SIZE (_sigpoll, 2*sizeof(int));
|
|
CHECK_SI_SIZE (_sigpoll, 4*sizeof(int));
|
|
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_band) != 0x10);
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_fd) != 0x18);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_band) != 0x0C);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_fd) != 0x10);
|
|
|
|
CHECK_CSI_OFFSET(_sigsys);
|
|
CHECK_CSI_SIZE (_sigsys, 3*sizeof(int));
|
|
CHECK_SI_SIZE (_sigsys, 4*sizeof(int));
|
|
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_call_addr) != 0x10);
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_syscall) != 0x18);
|
|
BUILD_BUG_ON(offsetof(siginfo_t, si_arch) != 0x1C);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_call_addr) != 0x0C);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_syscall) != 0x10);
|
|
BUILD_BUG_ON(offsetof(compat_siginfo_t, si_arch) != 0x14);
|
|
|
|
/* any new si_fields should be added here */
|
|
}
|
|
|
|
void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact)
|
|
{
|
|
signal_compat_build_tests();
|
|
|
|
if (!act)
|
|
return;
|
|
|
|
if (in_ia32_syscall())
|
|
act->sa.sa_flags |= SA_IA32_ABI;
|
|
if (in_x32_syscall())
|
|
act->sa.sa_flags |= SA_X32_ABI;
|
|
}
|