* [PATCH 0/8] signal: Fix sending signals with siginfo [not found] ` <20170616191602.GA10675@1wt.eu> @ 2017-06-30 12:36 ` Eric W. Biederman 2017-07-18 14:04 ` [PATCH v2 0/7] " Eric W. Biederman 0 siblings, 1 reply; 24+ messages in thread From: Eric W. Biederman @ 2017-06-30 12:36 UTC (permalink / raw) To: linux-kernel Cc: Andy Lutomirski, Linus Torvalds, Al Viro, Oleg Nesterov, Andrei Vagin, Thomas Gleixner, Greg KH, Andrey Vagin, Serge Hallyn, Pavel Emelyanov, Cyrill Gorcunov, Peter Zijlstra, Willy Tarreau, linux-arch, linux-api, Linux Containers, Michael Kerrisk Today sending a signal with rt_sigqueueinfo and receving it on a signalfd does not work reliably. The issue is that reading a signalfd instead of returning a siginfo returns a signalfd_siginfo and the kernel must convert from one to the other. The kernel does not currently have the code to deduce which union members of struct siginfo are in use. In this patchset I fix that by introducing a new function siginfo_layout that can look at a siginfo and report which union member of struct nnsiginfo is in use. Before that I clean up how we populate struct siginfo. The siginfo structure has two key members si_signo and si_code. Some si_codes are signal specific and for those it takes si_signo and si_code to indicate the members of siginfo that are valid. The rest of the si_code values are signal independent like SI_USER, SI_KERNEL, SI_QUEUE, and SI_TIMER and only si_code is needed to indicate which members of siginfo are valid. At least that is how POSIX documents them, and how common sense would indicate they should function. In practice we have been rather sloppy about maintaining the ABI in linux and we have some exceptions. We have a couple of buggy architectures that make SI_USER mean something different when combined with SIGFPE or SIGTRAP. Worse we have fcntl(F_SETSIG) which results in the si_codes POLL_IN, POLL_OUT, POLL_MSG, POLL_ERR, POLL_PRI, POLL_HUP being sent with any arbitrary signal, while the values are in a range that overlaps the signal specific si_codes. Thankfully the ambiguous cases are for things no sane persion would do that so we can rectify the situtation. AKA no one cares so we won't cause a regression fixing it. As part of fixing this I stop leaking the __SI_xxxx codes to userspace and stop storing them in the high 16bits of si_code. Making the kernel code fundamentally simpler. We have already confirmed that the one application that would see this difference in kernel behavior CRIU won't be affected by this change as it copies values verbatim from one kernel interface to another. Eric Eric W. Biederman (8): signal/alpha: Document a conflict with SI_USER for SIGTRAP signal/ia64: Document a conflict with SI_USER with SIGFPE signal/sparc: Document a conflict with SI_USER with SIGFPE signal/mips: Document a conflict with SI_USER with SIGFPE signal/testing: Don't look for __SI_FAULT in userspace signal/x86: Fix SIGSYS handling in copy_siginfo_to_user32 fcntl: Don't use ambiguous SIG_POLL si_codes signal: Remove kernel interal si_code magic arch/alpha/include/uapi/asm/siginfo.h | 5 ++ arch/alpha/kernel/traps.c | 6 +- arch/arm64/kernel/signal32.c | 23 +++--- arch/blackfin/include/uapi/asm/siginfo.h | 30 +++++--- arch/frv/include/uapi/asm/siginfo.h | 2 +- arch/ia64/include/uapi/asm/siginfo.h | 19 ++--- arch/ia64/kernel/signal.c | 17 ++--- arch/ia64/kernel/traps.c | 4 +- arch/mips/include/uapi/asm/siginfo.h | 9 ++- arch/mips/kernel/signal32.c | 19 +++-- arch/mips/kernel/traps.c | 2 +- arch/parisc/kernel/signal32.c | 31 ++++---- arch/powerpc/kernel/signal_32.c | 20 +++-- arch/s390/kernel/compat_signal.c | 32 ++++---- arch/sparc/include/uapi/asm/siginfo.h | 7 +- arch/sparc/kernel/signal32.c | 16 ++-- arch/sparc/kernel/traps_32.c | 2 +- arch/sparc/kernel/traps_64.c | 2 +- arch/tile/include/uapi/asm/siginfo.h | 4 +- arch/tile/kernel/compat_signal.c | 18 ++--- arch/tile/kernel/traps.c | 1 - arch/x86/kernel/signal_compat.c | 22 +++--- fs/fcntl.c | 13 +++- fs/signalfd.c | 22 ++---- include/asm-generic/siginfo.h | 22 +++--- include/linux/signal.h | 8 ++ include/uapi/asm-generic/siginfo.h | 104 ++++++++++++-------------- kernel/compat.c | 2 - kernel/exit.c | 6 +- kernel/ptrace.c | 6 +- kernel/signal.c | 72 +++++++++++++----- tools/testing/selftests/x86/mpx-mini-test.c | 3 +- tools/testing/selftests/x86/protection_keys.c | 13 ++-- 33 files changed, 302 insertions(+), 260 deletions(-) ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v2 0/7] signal: Fix sending signals with siginfo 2017-06-30 12:36 ` [PATCH 0/8] signal: Fix sending signals with siginfo Eric W. Biederman @ 2017-07-18 14:04 ` Eric W. Biederman 2017-07-18 14:06 ` [PATCH 1/7] signal/alpha: Document a conflict with SI_USER for SIGTRAP Eric W. Biederman ` (2 more replies) 0 siblings, 3 replies; 24+ messages in thread From: Eric W. Biederman @ 2017-07-18 14:04 UTC (permalink / raw) To: linux-kernel Cc: Andy Lutomirski, Linus Torvalds, Al Viro, Oleg Nesterov, Andrei Vagin, Thomas Gleixner, Greg KH, Andrey Vagin, Serge Hallyn, Pavel Emelyanov, Cyrill Gorcunov, Peter Zijlstra, Willy Tarreau, linux-arch, linux-api, Linux Containers, Michael Kerrisk Today sending a signal with rt_sigqueueinfo and receving it on a signalfd does not work reliably. The issue is that reading a signalfd instead of returning a siginfo returns a signalfd_siginfo and the kernel must convert from one to the other. The kernel does not currently have the code to deduce which union members of struct siginfo are in use. In this patchset I fix that by introducing a new function siginfo_layout that can look at a siginfo and report which union member of struct siginfo is in use. Before that I clean up how we populate struct siginfo. The siginfo structure has two key members si_signo and si_code. Some si_codes are signal specific and for those it takes si_signo and si_code to indicate the members of siginfo that are valid. The rest of the si_code values are signal independent like SI_USER, SI_KERNEL, SI_QUEUE, and SI_TIMER and only si_code is needed to indicate which members of siginfo are valid. At least that is how POSIX documents them, and how common sense would indicate they should function. In practice we have been rather sloppy about maintaining the ABI in linux and we have some exceptions. We have a couple of buggy architectures that make SI_USER mean something different when combined with SIGFPE or SIGTRAP. Worse we have fcntl(F_SETSIG) which results in the si_codes POLL_IN, POLL_OUT, POLL_MSG, POLL_ERR, POLL_PRI, POLL_HUP being sent with any arbitrary signal, while the values are in a range that overlaps the signal specific si_codes. Thankfully the ambiguous cases with the POLL_NNN si_codes are for things no sane persion would do that so we can rectify the situtation. AKA no one cares so we won't cause a regression fixing it. As part of fixing this I stop leaking the __SI_xxxx codes to userspace and stop storing them in the high 16bits of si_code. Making the kernel code fundamentally simpler. We have already confirmed that the one application that would see this difference in kernel behavior CRIU won't be affected by this change as it copies values verbatim from one kernel interface to another. v2: - Benchmarked the code to confirm no performance changes are visible. - Reworked the first couple of patches so that TRAP_FIXME and FPE_FIXME are not exported to userspace. - Rebased on top of the siginfo cleanup that came in v4.13-rc1 - Updated alpha to use both TRAP_FIXME and FPE_FIXME Eric W. Biederman (7): signal/alpha: Document a conflict with SI_USER for SIGTRAP signal/ia64: Document a conflict with SI_USER with SIGFPE signal/sparc: Document a conflict with SI_USER with SIGFPE signal/mips: Document a conflict with SI_USER with SIGFPE signal/testing: Don't look for __SI_FAULT in userspace fcntl: Don't use ambiguous SIG_POLL si_codes signal: Remove kernel interal si_code magic arch/alpha/include/uapi/asm/siginfo.h | 14 ++++ arch/alpha/kernel/traps.c | 6 +- arch/arm64/kernel/signal32.c | 23 ++---- arch/blackfin/include/uapi/asm/siginfo.h | 30 ++++--- arch/frv/include/uapi/asm/siginfo.h | 2 +- arch/ia64/include/uapi/asm/siginfo.h | 21 +++-- arch/ia64/kernel/signal.c | 17 ++-- arch/ia64/kernel/traps.c | 4 +- arch/mips/include/uapi/asm/siginfo.h | 11 ++- arch/mips/kernel/signal32.c | 19 ++--- arch/mips/kernel/traps.c | 2 +- arch/parisc/kernel/signal32.c | 31 ++++--- arch/powerpc/kernel/signal_32.c | 20 ++--- arch/s390/kernel/compat_signal.c | 32 ++++--- arch/sparc/include/uapi/asm/siginfo.h | 9 +- arch/sparc/kernel/signal32.c | 16 ++-- arch/sparc/kernel/traps_32.c | 2 +- arch/sparc/kernel/traps_64.c | 2 +- arch/tile/include/uapi/asm/siginfo.h | 4 +- arch/tile/kernel/compat_signal.c | 18 ++-- arch/tile/kernel/traps.c | 2 +- arch/x86/kernel/signal_compat.c | 21 ++--- fs/fcntl.c | 13 ++- fs/signalfd.c | 22 ++--- include/linux/signal.h | 22 +++++ include/uapi/asm-generic/siginfo.h | 115 +++++++++++--------------- kernel/exit.c | 4 +- kernel/ptrace.c | 6 +- kernel/signal.c | 72 ++++++++++++---- tools/testing/selftests/x86/mpx-mini-test.c | 3 +- tools/testing/selftests/x86/protection_keys.c | 13 ++- 31 files changed, 318 insertions(+), 258 deletions(-) ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 1/7] signal/alpha: Document a conflict with SI_USER for SIGTRAP 2017-07-18 14:04 ` [PATCH v2 0/7] " Eric W. Biederman @ 2017-07-18 14:06 ` Eric W. Biederman [not found] ` <20170718140651.15973-1-ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> 2017-07-18 14:06 ` [PATCH 4/7] signal/mips: Document a conflict with SI_USER with SIGFPE Eric W. Biederman [not found] ` <87o9shg7t7.fsf_-_-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> 2 siblings, 1 reply; 24+ messages in thread From: Eric W. Biederman @ 2017-07-18 14:06 UTC (permalink / raw) To: linux-kernel Cc: Andy Lutomirski, Linus Torvalds, Al Viro, Oleg Nesterov, Andrei Vagin, Thomas Gleixner, Greg KH, Andrey Vagin, Serge Hallyn, Pavel Emelyanov, Cyrill Gorcunov, Peter Zijlstra, Willy Tarreau, linux-arch, linux-api, Linux Containers, Michael Kerrisk, Eric W. Biederman, Helge Deller, Richard Henderson, Ivan Kokshaysky Setting si_code to __SI_FAULT results in a userspace seeing an si_code of 0. This is the same si_code as SI_USER. Posix and common sense requires that SI_USER not be a signal specific si_code. As such this use of 0 for the si_code is a pretty horribly broken ABI. Given that alpha is on it's last legs I don't know that it is worth fixing this, but it is worth documenting what is going on so that no one decides to copy this bad decision. This was introduced during the 2.5 development cycle so this mess has had a long time for people to be able to depend upon it. v2: Added FPE_FIXME for alpha as Helge Deller <deller@gmx.de> pointed out with his alternate patch one of the cases is SIGFPE not SIGTRAP. Cc: Helge Deller <deller@gmx.de> Cc: Richard Henderson <rth@twiddle.net> Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru> Cc: Matt Turner <mattst88@gmail.com> Cc: linux-alpha@vger.kernel.org History Tree: https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git Ref: 0a635c7a84cf ("Fill in siginfo_t.") Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> --- arch/alpha/include/uapi/asm/siginfo.h | 14 ++++++++++++++ arch/alpha/kernel/traps.c | 6 +++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/arch/alpha/include/uapi/asm/siginfo.h b/arch/alpha/include/uapi/asm/siginfo.h index 9822362a8424..972f547d9e41 100644 --- a/arch/alpha/include/uapi/asm/siginfo.h +++ b/arch/alpha/include/uapi/asm/siginfo.h @@ -6,4 +6,18 @@ #include <asm-generic/siginfo.h> +/* + * SIGFPE si_codes + */ +#ifdef __KERNEL__ +#define FPE_FIXME (__SI_FAULT|0) /* Broken dup of SI_USER */ +#endif /* __KERNEL__ */ + +/* + * SIGTRAP si_codes + */ +#ifdef __KERNEL__ +#define TRAP_FIXME (__SI_FAULT|0) /* Broken dup of SI_USER */ +#endif /* __KERNEL__ */ + #endif diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index 65bb102d985b..e94f4b73ac04 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -278,7 +278,7 @@ do_entIF(unsigned long type, struct pt_regs *regs) case 1: /* bugcheck */ info.si_signo = SIGTRAP; info.si_errno = 0; - info.si_code = __SI_FAULT; + info.si_code = TRAP_FIXME; info.si_addr = (void __user *) regs->pc; info.si_trapno = 0; send_sig_info(SIGTRAP, &info, current); @@ -318,7 +318,7 @@ do_entIF(unsigned long type, struct pt_regs *regs) break; case GEN_ROPRAND: signo = SIGFPE; - code = __SI_FAULT; + code = FPE_FIXME; break; case GEN_DECOVF: @@ -340,7 +340,7 @@ do_entIF(unsigned long type, struct pt_regs *regs) case GEN_SUBRNG7: default: signo = SIGTRAP; - code = __SI_FAULT; + code = TRAP_FIXME; break; } -- 2.10.1 ^ permalink raw reply related [flat|nested] 24+ messages in thread
[parent not found: <20170718140651.15973-1-ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>]
* Re: [PATCH 1/7] signal/alpha: Document a conflict with SI_USER for SIGTRAP [not found] ` <20170718140651.15973-1-ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> @ 2017-07-18 18:22 ` Richard Henderson 0 siblings, 0 replies; 24+ messages in thread From: Richard Henderson @ 2017-07-18 18:22 UTC (permalink / raw) To: Eric W. Biederman, linux-kernel-u79uwXL29TY76Z2rM5mHXA Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Andrei Vagin, Greg KH, Linux Containers, linux-alpha-u79uwXL29TY76Z2rM5mHXA, Pavel Emelyanov, Oleg Nesterov, Matt Turner, Ivan Kokshaysky, Al Viro, Andy Lutomirski, linux-api-u79uwXL29TY76Z2rM5mHXA, Cyrill Gorcunov, Michael Kerrisk, Thomas Gleixner, Linus Torvalds, Willy Tarreau, Helge Deller, Andrey Vagin On 07/18/2017 04:06 AM, Eric W. Biederman wrote: > Setting si_code to __SI_FAULT results in a userspace seeing > an si_code of 0. This is the same si_code as SI_USER. Posix > and common sense requires that SI_USER not be a signal specific > si_code. As such this use of 0 for the si_code is a pretty > horribly broken ABI. > > Given that alpha is on it's last legs I don't know that it is worth > fixing this, but it is worth documenting what is going on so that > no one decides to copy this bad decision. > > This was introduced during the 2.5 development cycle so this > mess has had a long time for people to be able to depend upon it. > > v2: Added FPE_FIXME for alpha as Helge Deller<deller-Mmb7MZpHnFY@public.gmane.org> pointed out > with his alternate patch one of the cases is SIGFPE not SIGTRAP. > > Cc: Helge Deller<deller-Mmb7MZpHnFY@public.gmane.org> > Cc: Richard Henderson<rth-hL46jP5Bxq7R7s880joybQ@public.gmane.org> > Cc: Ivan Kokshaysky<ink-biIs/Y0ymYJMZLIVYojuPNP0rXTJTi09@public.gmane.org> > Cc: Matt Turner<mattst88-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > Cc:linux-alpha-u79uwXL29TY76Z2rM5mHXA@public.gmane.org > History Tree:https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git > Ref: 0a635c7a84cf ("Fill in siginfo_t.") > Signed-off-by: "Eric W. Biederman"<ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> > --- > arch/alpha/include/uapi/asm/siginfo.h | 14 ++++++++++++++ > arch/alpha/kernel/traps.c | 6 +++--- > 2 files changed, 17 insertions(+), 3 deletions(-) Acked-by: Richard Henderson <rth-hL46jP5Bxq7R7s880joybQ@public.gmane.org> r~ ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 4/7] signal/mips: Document a conflict with SI_USER with SIGFPE 2017-07-18 14:04 ` [PATCH v2 0/7] " Eric W. Biederman 2017-07-18 14:06 ` [PATCH 1/7] signal/alpha: Document a conflict with SI_USER for SIGTRAP Eric W. Biederman @ 2017-07-18 14:06 ` Eric W. Biederman 2017-08-07 16:18 ` Maciej W. Rozycki [not found] ` <87o9shg7t7.fsf_-_-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> 2 siblings, 1 reply; 24+ messages in thread From: Eric W. Biederman @ 2017-07-18 14:06 UTC (permalink / raw) To: linux-kernel Cc: Andy Lutomirski, Linus Torvalds, Al Viro, Oleg Nesterov, Andrei Vagin, Thomas Gleixner, Greg KH, Andrey Vagin, Serge Hallyn, Pavel Emelyanov, Cyrill Gorcunov, Peter Zijlstra, Willy Tarreau, linux-arch, linux-api, Linux Containers, Michael Kerrisk, Eric W. Biederman, Ralf Baechle Setting si_code to __SI_FAULT results in a userspace seeing an si_code of 0. This is the same si_code as SI_USER. Posix and common sense requires that SI_USER not be a signal specific si_code. As such this use of 0 for the si_code is a pretty horribly broken ABI. This use of of __SI_FAULT is only a decade old. Which compared to the other pieces of kernel code that has made this mistake is almost yesterday. This is probably worth fixing but I don't know mips well enough to know what si_code to would be the proper one to use. Cc: Ralf Baechle <ralf@linux-mips.org> Ref: 948a34cf3988 ("[MIPS] Maintain si_code field properly for FP exceptions") Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> --- arch/mips/include/uapi/asm/siginfo.h | 7 +++++++ arch/mips/kernel/traps.c | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/mips/include/uapi/asm/siginfo.h b/arch/mips/include/uapi/asm/siginfo.h index 8069cf766603..9becfd102132 100644 --- a/arch/mips/include/uapi/asm/siginfo.h +++ b/arch/mips/include/uapi/asm/siginfo.h @@ -123,4 +123,11 @@ typedef struct siginfo { #define SI_TIMER __SI_CODE(__SI_TIMER, -3) /* sent by timer expiration */ #define SI_MESGQ __SI_CODE(__SI_MESGQ, -4) /* sent by real time mesq state change */ +/* + * SIGFPE si_codes + */ +#ifdef __KERNEL__ +#define FPE_FIXME (__SI_FAULT|0) /* Broken dup of SI_USER */ +#endif /* __KERNEL__ */ + #endif /* _UAPI_ASM_SIGINFO_H */ diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index b68b4d0726d3..6c9cca9c5341 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -735,7 +735,7 @@ void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr, else if (fcr31 & FPU_CSR_INE_X) si.si_code = FPE_FLTRES; else - si.si_code = __SI_FAULT; + si.si_code = FPE_FIXME; force_sig_info(SIGFPE, &si, tsk); } -- 2.10.1 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 4/7] signal/mips: Document a conflict with SI_USER with SIGFPE 2017-07-18 14:06 ` [PATCH 4/7] signal/mips: Document a conflict with SI_USER with SIGFPE Eric W. Biederman @ 2017-08-07 16:18 ` Maciej W. Rozycki 2017-08-07 17:41 ` Linus Torvalds 2017-08-08 15:29 ` Eric W. Biederman 0 siblings, 2 replies; 24+ messages in thread From: Maciej W. Rozycki @ 2017-08-07 16:18 UTC (permalink / raw) To: Eric W. Biederman Cc: linux-kernel, Andy Lutomirski, Linus Torvalds, Al Viro, Oleg Nesterov, Andrei Vagin, Thomas Gleixner, Greg KH, Andrey Vagin, Serge Hallyn, Pavel Emelyanov, Cyrill Gorcunov, Peter Zijlstra, Willy Tarreau, linux-arch, linux-api, Linux Containers, Michael Kerrisk, Ralf Baechle On Tue, 18 Jul 2017, Eric W. Biederman wrote: > diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c > index b68b4d0726d3..6c9cca9c5341 100644 > --- a/arch/mips/kernel/traps.c > +++ b/arch/mips/kernel/traps.c > @@ -735,7 +735,7 @@ void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr, > else if (fcr31 & FPU_CSR_INE_X) > si.si_code = FPE_FLTRES; > else > - si.si_code = __SI_FAULT; > + si.si_code = FPE_FIXME; This is an "impossible" state to reach unless your hardware is on fire. One or more of the FCSR Cause bits will have been set (in `fcr31') or the FPE exception would not have happened. Of course there could be a simulator bug, or we could have breakage somewhere causing `process_fpemu_return' to be called with SIGFPE and inconsistent `fcr31'. So we need to handle it somehow. So what would be the right value of `si_code' to use here for such an unexpected exception condition? I think `BUG()' would be too big a hammer here. Or wouldn't it? Maciej ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 4/7] signal/mips: Document a conflict with SI_USER with SIGFPE 2017-08-07 16:18 ` Maciej W. Rozycki @ 2017-08-07 17:41 ` Linus Torvalds 2017-08-07 19:55 ` Ralf Baechle 2017-08-08 15:29 ` Eric W. Biederman 1 sibling, 1 reply; 24+ messages in thread From: Linus Torvalds @ 2017-08-07 17:41 UTC (permalink / raw) To: Maciej W. Rozycki Cc: Eric W. Biederman, Linux Kernel Mailing List, Andy Lutomirski, Al Viro, Oleg Nesterov, Andrei Vagin, Thomas Gleixner, Greg KH, Andrey Vagin, Serge Hallyn, Pavel Emelyanov, Cyrill Gorcunov, Peter Zijlstra, Willy Tarreau, linux-arch, Linux API, Linux Containers, Michael Kerrisk, Ralf Baechle On Mon, Aug 7, 2017 at 9:18 AM, Maciej W. Rozycki <macro@imgtec.com> wrote: > > So what would be the right value of `si_code' to use here for such an > unexpected exception condition? I think `BUG()' would be too big a > hammer here. Or wouldn't it? Hell no. NEVER EVER BUG(). The only case to use BUG() is if there is some core data structure (say, kernel stack) that is so corrupted that you know you cannot continue. That's the *only* valid use. If this is a "this condition cannot happen" issue, then just remove the damn conditional. It's pointless. Adding a BUG() to show "this cannot happen" is not acceptable. Linus ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 4/7] signal/mips: Document a conflict with SI_USER with SIGFPE 2017-08-07 17:41 ` Linus Torvalds @ 2017-08-07 19:55 ` Ralf Baechle 0 siblings, 0 replies; 24+ messages in thread From: Ralf Baechle @ 2017-08-07 19:55 UTC (permalink / raw) To: Linus Torvalds Cc: Maciej W. Rozycki, Eric W. Biederman, Linux Kernel Mailing List, Andy Lutomirski, Al Viro, Oleg Nesterov, Andrei Vagin, Thomas Gleixner, Greg KH, Andrey Vagin, Serge Hallyn, Pavel Emelyanov, Cyrill Gorcunov, Peter Zijlstra, Willy Tarreau, linux-arch, Linux API, Linux Containers, Michael Kerrisk On Mon, Aug 07, 2017 at 10:41:39AM -0700, Linus Torvalds wrote: > On Mon, Aug 7, 2017 at 9:18 AM, Maciej W. Rozycki <macro@imgtec.com> wrote: > > > > So what would be the right value of `si_code' to use here for such an > > unexpected exception condition? I think `BUG()' would be too big a > > hammer here. Or wouldn't it? > > Hell no. NEVER EVER BUG(). > > The only case to use BUG() is if there is some core data structure > (say, kernel stack) that is so corrupted that you know you cannot > continue. That's the *only* valid use. > > If this is a "this condition cannot happen" issue, then just remove > the damn conditional. It's pointless. Adding a BUG() to show "this > cannot happen" is not acceptable. I queued a patch to remove the code for 4.14. Ralf ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 4/7] signal/mips: Document a conflict with SI_USER with SIGFPE 2017-08-07 16:18 ` Maciej W. Rozycki 2017-08-07 17:41 ` Linus Torvalds @ 2017-08-08 15:29 ` Eric W. Biederman 2017-08-08 23:19 ` Maciej W. Rozycki 1 sibling, 1 reply; 24+ messages in thread From: Eric W. Biederman @ 2017-08-08 15:29 UTC (permalink / raw) To: Maciej W. Rozycki Cc: linux-kernel, Andy Lutomirski, Linus Torvalds, Al Viro, Oleg Nesterov, Andrei Vagin, Thomas Gleixner, Greg KH, Andrey Vagin, Serge Hallyn, Pavel Emelyanov, Cyrill Gorcunov, Peter Zijlstra, Willy Tarreau, linux-arch, linux-api, Linux Containers, Michael Kerrisk, Ralf Baechle "Maciej W. Rozycki" <macro@imgtec.com> writes: > On Tue, 18 Jul 2017, Eric W. Biederman wrote: > >> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c >> index b68b4d0726d3..6c9cca9c5341 100644 >> --- a/arch/mips/kernel/traps.c >> +++ b/arch/mips/kernel/traps.c >> @@ -735,7 +735,7 @@ void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr, >> else if (fcr31 & FPU_CSR_INE_X) >> si.si_code = FPE_FLTRES; >> else >> - si.si_code = __SI_FAULT; >> + si.si_code = FPE_FIXME; > > This is an "impossible" state to reach unless your hardware is on fire. > One or more of the FCSR Cause bits will have been set (in `fcr31') or the > FPE exception would not have happened. > > Of course there could be a simulator bug, or we could have breakage > somewhere causing `process_fpemu_return' to be called with SIGFPE and > inconsistent `fcr31'. So we need to handle it somehow. > > So what would be the right value of `si_code' to use here for such an > unexpected exception condition? I think `BUG()' would be too big a > hammer here. Or wouldn't it? The possible solutions I can think of are: WARN_ON_ONCE with a comment. Add a new si_code to uapi/asm-generic/siginfo.h perhaps FPE_IMPOSSIBLE. Like syscall numbers si_codes are cheap. Call force_sig() instead of force_sig_info, using just a generic si_code. If this is truly impossible and the compiler doesn't complain just drop the code. Eric ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 4/7] signal/mips: Document a conflict with SI_USER with SIGFPE 2017-08-08 15:29 ` Eric W. Biederman @ 2017-08-08 23:19 ` Maciej W. Rozycki 0 siblings, 0 replies; 24+ messages in thread From: Maciej W. Rozycki @ 2017-08-08 23:19 UTC (permalink / raw) To: Eric W. Biederman Cc: linux-kernel, Andy Lutomirski, Linus Torvalds, Al Viro, Oleg Nesterov, Andrei Vagin, Thomas Gleixner, Greg KH, Andrey Vagin, Serge Hallyn, Pavel Emelyanov, Cyrill Gorcunov, Peter Zijlstra, Willy Tarreau, linux-arch, linux-api, Linux Containers, Michael Kerrisk, Ralf Baechle On Tue, 8 Aug 2017, Eric W. Biederman wrote: > > This is an "impossible" state to reach unless your hardware is on fire. > > One or more of the FCSR Cause bits will have been set (in `fcr31') or the > > FPE exception would not have happened. > > > > Of course there could be a simulator bug, or we could have breakage > > somewhere causing `process_fpemu_return' to be called with SIGFPE and > > inconsistent `fcr31'. So we need to handle it somehow. > > > > So what would be the right value of `si_code' to use here for such an > > unexpected exception condition? I think `BUG()' would be too big a > > hammer here. Or wouldn't it? > > The possible solutions I can think of are: > > WARN_ON_ONCE with a comment. > > Add a new si_code to uapi/asm-generic/siginfo.h perhaps FPE_IMPOSSIBLE. > Like syscall numbers si_codes are cheap. I think we ought to do both. First, we have our own FP emulation code, which is changed from time to time, that uses the same exit path that the hardware exception does. It could happen that we miss something and return SIGFPE from the emulation code without setting the cause bits appropriately. This would be our own bug which might trigger exceedingly rarely and could then be caught by WARN_ON_ONCE or otherwise stay there forever in the absence of that check. Second, changing `si_code' from __SI_FAULT to 0 aka __SI_KILL will likely interfere with `copy_siginfo_to_user32' in arch/mips/kernel/signal32.c, making the userland lose the address of the faulting instruction in 32-bit software run on 64-bit hardware only, making our API inconsistent. Using a distinct `si_code' value such as FPE_IMPOSSIBLE (though we might choose say FPE_FLTUNK for "FLoaTing point UNKnown" instead, for consistency; mind that most `si_code' macros have the same number of characters within groups associated with individual signals) for such odd traps is allowed by SUS and will prevent the inconsistency from happening, very cheaply as you say. Maciej ^ permalink raw reply [flat|nested] 24+ messages in thread
[parent not found: <87o9shg7t7.fsf_-_-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>]
* [PATCH 2/7] signal/ia64: Document a conflict with SI_USER with SIGFPE [not found] ` <87o9shg7t7.fsf_-_-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> @ 2017-07-18 14:06 ` Eric W. Biederman 2017-07-18 14:06 ` [PATCH 3/7] signal/sparc: " Eric W. Biederman ` (3 subsequent siblings) 4 siblings, 0 replies; 24+ messages in thread From: Eric W. Biederman @ 2017-07-18 14:06 UTC (permalink / raw) To: linux-kernel-u79uwXL29TY76Z2rM5mHXA Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Fenghua Yu, Eric W. Biederman, linux-ia64-u79uwXL29TY76Z2rM5mHXA, Andrei Vagin, Greg KH, Linux Containers, Pavel Emelyanov, Oleg Nesterov, Tony Luck, Al Viro, Andy Lutomirski, linux-api-u79uwXL29TY76Z2rM5mHXA, Cyrill Gorcunov, Michael Kerrisk, Thomas Gleixner, Linus Torvalds, Willy Tarreau, Andrey Vagin Setting si_code to __SI_FAULT results in a userspace seeing an si_code of 0. This is the same si_code as SI_USER. Posix and common sense requires that SI_USER not be a signal specific si_code. As such this use of 0 for the si_code is a pretty horribly broken ABI. Given that ia64 is on it's last legs I don't know that it is worth fixing this, but it is worth documenting what is going on so that no one decides to copy this bad decision. This was introduced in 2.3.51 so this mess has had a long time for people to be able to start depending on it. Cc: Tony Luck <tony.luck-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> Cc: Fenghua Yu <fenghua.yu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> Cc: linux-ia64-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Signed-off-by: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> --- arch/ia64/include/uapi/asm/siginfo.h | 3 +++ arch/ia64/kernel/traps.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/ia64/include/uapi/asm/siginfo.h b/arch/ia64/include/uapi/asm/siginfo.h index 4694c64252d6..3282f8b992fc 100644 --- a/arch/ia64/include/uapi/asm/siginfo.h +++ b/arch/ia64/include/uapi/asm/siginfo.h @@ -107,6 +107,9 @@ typedef struct siginfo { /* * SIGFPE si_codes */ +#ifdef __KERNEL__ +#define FPE_FIXME (__SI_FAULT|0) /* Broken dup of SI_USER */ +#endif /* __KERNEL__ */ #define __FPE_DECOVF (__SI_FAULT|9) /* decimal overflow */ #define __FPE_DECDIV (__SI_FAULT|10) /* decimal division by zero */ #define __FPE_DECERR (__SI_FAULT|11) /* packed decimal error */ diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index 7b1fe9462158..3cb17cf9b362 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c @@ -349,7 +349,7 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr) } siginfo.si_signo = SIGFPE; siginfo.si_errno = 0; - siginfo.si_code = __SI_FAULT; /* default code */ + siginfo.si_code = FPE_FIXME; /* default code */ siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); if (isr & 0x11) { siginfo.si_code = FPE_FLTINV; @@ -373,7 +373,7 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr) /* raise exception */ siginfo.si_signo = SIGFPE; siginfo.si_errno = 0; - siginfo.si_code = __SI_FAULT; /* default code */ + siginfo.si_code = FPE_FIXME; /* default code */ siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); if (isr & 0x880) { siginfo.si_code = FPE_FLTOVF; -- 2.10.1 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 3/7] signal/sparc: Document a conflict with SI_USER with SIGFPE [not found] ` <87o9shg7t7.fsf_-_-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> 2017-07-18 14:06 ` [PATCH 2/7] signal/ia64: " Eric W. Biederman @ 2017-07-18 14:06 ` Eric W. Biederman 2017-07-18 14:06 ` [PATCH 5/7] signal/testing: Don't look for __SI_FAULT in userspace Eric W. Biederman ` (2 subsequent siblings) 4 siblings, 0 replies; 24+ messages in thread From: Eric W. Biederman @ 2017-07-18 14:06 UTC (permalink / raw) To: linux-kernel-u79uwXL29TY76Z2rM5mHXA Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Eric W. Biederman, Andrei Vagin, Greg KH, Linux Containers, Pavel Emelyanov, Oleg Nesterov, David S. Miller, sparclinux-u79uwXL29TY76Z2rM5mHXA, Al Viro, Andy Lutomirski, linux-api-u79uwXL29TY76Z2rM5mHXA, Cyrill Gorcunov, Michael Kerrisk, Thomas Gleixner, Linus Torvalds, Willy Tarreau, Andrey Vagin Setting si_code to __SI_FAULT results in a userspace seeing an si_code of 0. This is the same si_code as SI_USER. Posix and common sense requires that SI_USER not be a signal specific si_code. As such this use of 0 for the si_code is a pretty horribly broken ABI. This was introduced in 2.3.41 so this mess has had a long time for people to be able to start depending on it. As this bug has existed for 17 years already I don't know if it is worth fixing. It is definitely worth documenting what is going on so that no one decides to copy this bad decision. Cc: "David S. Miller" <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org> Cc: sparclinux-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Signed-off-by: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> --- arch/sparc/include/uapi/asm/siginfo.h | 7 +++++++ arch/sparc/kernel/traps_32.c | 2 +- arch/sparc/kernel/traps_64.c | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/sparc/include/uapi/asm/siginfo.h b/arch/sparc/include/uapi/asm/siginfo.h index 2d9b79ccaa50..da2126e0c536 100644 --- a/arch/sparc/include/uapi/asm/siginfo.h +++ b/arch/sparc/include/uapi/asm/siginfo.h @@ -17,6 +17,13 @@ #define SI_NOINFO 32767 /* no information in siginfo_t */ /* + * SIGFPE si_codes + */ +#ifdef __KERNEL__ +#define FPE_FIXME (__SI_FAULT|0) /* Broken dup of SI_USER */ +#endif /* __KERNEL__ */ + +/* * SIGEMT si_codes */ #define EMT_TAGOVF (__SI_FAULT|1) /* tag overflow */ diff --git a/arch/sparc/kernel/traps_32.c b/arch/sparc/kernel/traps_32.c index 466d4aed06c7..581cf35ee7e3 100644 --- a/arch/sparc/kernel/traps_32.c +++ b/arch/sparc/kernel/traps_32.c @@ -306,7 +306,7 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc, info.si_errno = 0; info.si_addr = (void __user *)pc; info.si_trapno = 0; - info.si_code = __SI_FAULT; + info.si_code = FPE_FIXME; if ((fsr & 0x1c000) == (1 << 14)) { if (fsr & 0x10) info.si_code = FPE_FLTINV; diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index 196ee5eb4d48..e882e128faa3 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c @@ -2258,7 +2258,7 @@ static void do_fpe_common(struct pt_regs *regs) info.si_errno = 0; info.si_addr = (void __user *)regs->tpc; info.si_trapno = 0; - info.si_code = __SI_FAULT; + info.si_code = FPE_FIXME; if ((fsr & 0x1c000) == (1 << 14)) { if (fsr & 0x10) info.si_code = FPE_FLTINV; -- 2.10.1 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 5/7] signal/testing: Don't look for __SI_FAULT in userspace [not found] ` <87o9shg7t7.fsf_-_-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> 2017-07-18 14:06 ` [PATCH 2/7] signal/ia64: " Eric W. Biederman 2017-07-18 14:06 ` [PATCH 3/7] signal/sparc: " Eric W. Biederman @ 2017-07-18 14:06 ` Eric W. Biederman 2017-07-18 14:06 ` [PATCH 6/7] fcntl: Don't use ambiguous SIG_POLL si_codes Eric W. Biederman 2017-07-18 14:06 ` [PATCH 7/7] signal: Remove kernel interal si_code magic Eric W. Biederman 4 siblings, 0 replies; 24+ messages in thread From: Eric W. Biederman @ 2017-07-18 14:06 UTC (permalink / raw) To: linux-kernel-u79uwXL29TY76Z2rM5mHXA Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Eric W. Biederman, Andrei Vagin, Greg KH, Linux Containers, Dave Hansen, Pavel Emelyanov, Oleg Nesterov, Al Viro, Andy Lutomirski, linux-api-u79uwXL29TY76Z2rM5mHXA, Cyrill Gorcunov, Michael Kerrisk, Thomas Gleixner, Linus Torvalds, Willy Tarreau, Andrey Vagin Fix the debug print statements in these tests where they reference si_codes and in particular __SI_FAULT. __SI_FAULT is a kernel internal value and should never be seen by userspace. While I am in there also fix si_code_str. si_codes are an enumeration there are not a bitmap so == and not & is the apropriate operation to test for an si_code. Cc: Dave Hansen <dave.hansen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> Fixes: 5f23f6d082a9 ("x86/pkeys: Add self-tests") Fixes: e754aedc26ef ("x86/mpx, selftests: Add MPX self test") Signed-off-by: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> --- tools/testing/selftests/x86/mpx-mini-test.c | 3 +-- tools/testing/selftests/x86/protection_keys.c | 13 ++++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/x86/mpx-mini-test.c b/tools/testing/selftests/x86/mpx-mini-test.c index a8df159a8924..ec0f6b45ce8b 100644 --- a/tools/testing/selftests/x86/mpx-mini-test.c +++ b/tools/testing/selftests/x86/mpx-mini-test.c @@ -391,8 +391,7 @@ void handler(int signum, siginfo_t *si, void *vucontext) br_count++; dprintf1("#BR 0x%jx (total seen: %d)\n", status, br_count); -#define __SI_FAULT (3 << 16) -#define SEGV_BNDERR (__SI_FAULT|3) /* failed address bound checks */ +#define SEGV_BNDERR 3 /* failed address bound checks */ dprintf2("Saw a #BR! status 0x%jx at %016lx br_reason: %jx\n", status, ip, br_reason); diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c index 3237bc010e1c..23927845518d 100644 --- a/tools/testing/selftests/x86/protection_keys.c +++ b/tools/testing/selftests/x86/protection_keys.c @@ -212,19 +212,18 @@ void dump_mem(void *dumpme, int len_bytes) } } -#define __SI_FAULT (3 << 16) -#define SEGV_BNDERR (__SI_FAULT|3) /* failed address bound checks */ -#define SEGV_PKUERR (__SI_FAULT|4) +#define SEGV_BNDERR 3 /* failed address bound checks */ +#define SEGV_PKUERR 4 static char *si_code_str(int si_code) { - if (si_code & SEGV_MAPERR) + if (si_code == SEGV_MAPERR) return "SEGV_MAPERR"; - if (si_code & SEGV_ACCERR) + if (si_code == SEGV_ACCERR) return "SEGV_ACCERR"; - if (si_code & SEGV_BNDERR) + if (si_code == SEGV_BNDERR) return "SEGV_BNDERR"; - if (si_code & SEGV_PKUERR) + if (si_code == SEGV_PKUERR) return "SEGV_PKUERR"; return "UNKNOWN"; } -- 2.10.1 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 6/7] fcntl: Don't use ambiguous SIG_POLL si_codes [not found] ` <87o9shg7t7.fsf_-_-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> ` (2 preceding siblings ...) 2017-07-18 14:06 ` [PATCH 5/7] signal/testing: Don't look for __SI_FAULT in userspace Eric W. Biederman @ 2017-07-18 14:06 ` Eric W. Biederman [not found] ` <20170718140651.15973-6-ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> 2017-07-18 14:06 ` [PATCH 7/7] signal: Remove kernel interal si_code magic Eric W. Biederman 4 siblings, 1 reply; 24+ messages in thread From: Eric W. Biederman @ 2017-07-18 14:06 UTC (permalink / raw) To: linux-kernel-u79uwXL29TY76Z2rM5mHXA Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Eric W. Biederman, Andrei Vagin, Greg KH, Linux Containers, Pavel Emelyanov, Oleg Nesterov, Al Viro, Andy Lutomirski, linux-api-u79uwXL29TY76Z2rM5mHXA, Cyrill Gorcunov, Michael Kerrisk, Thomas Gleixner, Linus Torvalds, Willy Tarreau, Andrey Vagin We have a weird and problematic intersection of features that when they all come together result in ambiguous siginfo values, that we can not support properly. - Supporting fcntl(F_SETSIG,...) with arbitrary valid signals. - Using positive values for POLL_IN, POLL_OUT, POLL_MSG, ..., etc that imply they are signal specific si_codes and using the aforementioned arbitrary signal to deliver them. - Supporting injection of arbitrary siginfo values for debugging and checkpoint/restore. The result is that just looking at siginfo si_codes of 1 to 6 are ambigious. It could either be a signal specific si_code or it could be a generic si_code. For most of the kernel this is a non-issue but for sending signals with siginfo it is impossible to play back the kernel signals and get the same result. Strictly speaking when the si_code was changed from SI_SIGIO to POLL_IN and friends between 2.2 and 2.4 this functionality was not ambiguous, as only real time signals were supported. Before 2.4 was released the kernel began supporting siginfo with non realtime signals so they could give details of why the signal was sent. The result is that if F_SETSIG is set to one of the signals with signal specific si_codes then user space can not know why the signal was sent. I grepped through a bunch of userspace programs using debian code search to get a feel for how often people choose a signal that results in an ambiguous si_code. I only found one program doing so and it was using SIGCHLD to test the F_SETSIG functionality, and did not appear to be a real world usage. Therefore the ambiguity does not appears to be a real world problem in practice. Remove the ambiguity while introducing the smallest chance of breakage by changing the si_code to SI_SIGIO when signals with signal specific si_codes are targeted. Fixes: v2.3.40 -- Added support for queueing non-rt signals Fixes: v2.3.21 -- Changed the si_code from SI_SIGIO Signed-off-by: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> --- fs/fcntl.c | 13 ++++++++++++- include/linux/signal.h | 8 ++++++++ include/uapi/asm-generic/siginfo.h | 4 ++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/fs/fcntl.c b/fs/fcntl.c index 3b01b646e528..cfee2e084dbb 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -741,10 +741,21 @@ static void send_sigio_to_task(struct task_struct *p, si.si_signo = signum; si.si_errno = 0; si.si_code = reason; + /* + * Posix definies POLL_IN and friends to be signal + * specific si_codes for SIG_POLL. Linux extended + * these si_codes to other signals in a way that is + * ambiguous if other signals also have signal + * specific si_codes. In that case use SI_SIGIO instead + * to remove the ambiguity. + */ + if (sig_specific_sicodes(signum)) + si.si_code = SI_SIGIO; + /* Make sure we are called with one of the POLL_* reasons, otherwise we could leak kernel stack into userspace. */ - BUG_ON((reason & __SI_MASK) != __SI_POLL); + BUG_ON((reason < POLL_IN) || (reason > NSIGPOLL)); if (reason - POLL_IN >= NSIGPOLL) si.si_band = ~0L; else diff --git a/include/linux/signal.h b/include/linux/signal.h index e2678b5dbb21..c97cc20369c0 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -380,10 +380,18 @@ int unhandled_signal(struct task_struct *tsk, int sig); rt_sigmask(SIGCONT) | rt_sigmask(SIGCHLD) | \ rt_sigmask(SIGWINCH) | rt_sigmask(SIGURG) ) +#define SIG_SPECIFIC_SICODES_MASK (\ + rt_sigmask(SIGILL) | rt_sigmask(SIGFPE) | \ + rt_sigmask(SIGSEGV) | rt_sigmask(SIGBUS) | \ + rt_sigmask(SIGTRAP) | rt_sigmask(SIGCHLD) | \ + rt_sigmask(SIGPOLL) | rt_sigmask(SIGSYS) | \ + SIGEMT_MASK ) + #define sig_kernel_only(sig) siginmask(sig, SIG_KERNEL_ONLY_MASK) #define sig_kernel_coredump(sig) siginmask(sig, SIG_KERNEL_COREDUMP_MASK) #define sig_kernel_ignore(sig) siginmask(sig, SIG_KERNEL_IGNORE_MASK) #define sig_kernel_stop(sig) siginmask(sig, SIG_KERNEL_STOP_MASK) +#define sig_specific_sicodes(sig) siginmask(sig, SIG_SPECIFIC_SICODES_MASK) #define sig_fatal(t, signr) \ (!siginmask(signr, SIG_KERNEL_IGNORE_MASK|SIG_KERNEL_STOP_MASK) && \ diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h index 9c4eca6b374a..9e956ea94d57 100644 --- a/include/uapi/asm-generic/siginfo.h +++ b/include/uapi/asm-generic/siginfo.h @@ -184,7 +184,7 @@ typedef struct siginfo { #define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */ #define SI_MESGQ __SI_CODE(__SI_MESGQ,-3) /* sent by real time mesq state change */ #define SI_ASYNCIO -4 /* sent by AIO completion */ -#define SI_SIGIO -5 /* sent by queued SIGIO */ +#define SI_SIGIO __SI_CODE(__SI_POLL,-5) /* sent by queued SIGIO */ #define SI_TKILL -6 /* sent by tkill system call */ #define SI_DETHREAD -7 /* sent by execve() killing subsidiary threads */ @@ -259,7 +259,7 @@ typedef struct siginfo { #define NSIGCHLD 6 /* - * SIGPOLL si_codes + * SIGPOLL (or any other signal without signal specific si_codes) si_codes */ #define POLL_IN (__SI_POLL|1) /* data input available */ #define POLL_OUT (__SI_POLL|2) /* output buffers available */ -- 2.10.1 ^ permalink raw reply related [flat|nested] 24+ messages in thread
[parent not found: <20170718140651.15973-6-ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>]
* Re: [PATCH 6/7] fcntl: Don't use ambiguous SIG_POLL si_codes [not found] ` <20170718140651.15973-6-ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> @ 2017-07-20 16:16 ` Oleg Nesterov 2017-07-21 2:33 ` Eric W. Biederman 0 siblings, 1 reply; 24+ messages in thread From: Oleg Nesterov @ 2017-07-20 16:16 UTC (permalink / raw) To: Eric W. Biederman Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Andrei Vagin, Greg KH, Linux Containers, Pavel Emelyanov, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Al Viro, Andy Lutomirski, linux-api-u79uwXL29TY76Z2rM5mHXA, Cyrill Gorcunov, Michael Kerrisk, Thomas Gleixner, Linus Torvalds, Willy Tarreau, Andrey Vagin On 07/18, Eric W. Biederman wrote: > > - BUG_ON((reason & __SI_MASK) != __SI_POLL); > + BUG_ON((reason < POLL_IN) || (reason > NSIGPOLL)); ^^^^^^^^^^^^^^^^^ looks obviously wrong? Say, POLL_IN is obviously > NSIGPOLL == 6. Probably you meant BUG_ON((reason < POLL_IN) || (reason - POLL_IN > NSIGPOLL) ? but this contradicts with the next line: > if (reason - POLL_IN >= NSIGPOLL) > si.si_band = ~0L; confused... Oleg. ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 6/7] fcntl: Don't use ambiguous SIG_POLL si_codes 2017-07-20 16:16 ` Oleg Nesterov @ 2017-07-21 2:33 ` Eric W. Biederman 0 siblings, 0 replies; 24+ messages in thread From: Eric W. Biederman @ 2017-07-21 2:33 UTC (permalink / raw) To: Oleg Nesterov Cc: linux-kernel, Andy Lutomirski, Linus Torvalds, Al Viro, Andrei Vagin, Thomas Gleixner, Greg KH, Andrey Vagin, Serge Hallyn, Pavel Emelyanov, Cyrill Gorcunov, Peter Zijlstra, Willy Tarreau, linux-arch, linux-api, Linux Containers, Michael Kerrisk Oleg Nesterov <oleg@redhat.com> writes: > On 07/18, Eric W. Biederman wrote: >> >> - BUG_ON((reason & __SI_MASK) != __SI_POLL); >> + BUG_ON((reason < POLL_IN) || (reason > NSIGPOLL)); > ^^^^^^^^^^^^^^^^^ > looks obviously wrong? Say, POLL_IN is obviously > NSIGPOLL == 6. Strictly speaking that code is wrong until the next patch when I remove __SI_POLL. That is my mistake. When the values are not their messed up internal kernel variants the code works fine and makes sense. #define POLL_IN 1 /* data input available */ #define POLL_OUT 2 /* output buffers available */ #define POLL_MSG 3 /* input message available */ #define POLL_ERR 4 /* i/o error */ #define POLL_PRI 5 /* high priority input available */ #define POLL_HUP 6 /* device disconnected */ #define NSIGPOLL 6 > Probably you meant > > BUG_ON((reason < POLL_IN) || (reason - POLL_IN > NSIGPOLL) > > ? > > but this contradicts with the next line: >> if (reason - POLL_IN >= NSIGPOLL) >> si.si_band = ~0L; > > confused... I am mystified why we test for a condition that we have been bugging on for ages. Eric ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 7/7] signal: Remove kernel interal si_code magic [not found] ` <87o9shg7t7.fsf_-_-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> ` (3 preceding siblings ...) 2017-07-18 14:06 ` [PATCH 6/7] fcntl: Don't use ambiguous SIG_POLL si_codes Eric W. Biederman @ 2017-07-18 14:06 ` Eric W. Biederman [not found] ` <20170718140651.15973-7-ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> 4 siblings, 1 reply; 24+ messages in thread From: Eric W. Biederman @ 2017-07-18 14:06 UTC (permalink / raw) To: linux-kernel-u79uwXL29TY76Z2rM5mHXA Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Eric W. Biederman, Andrei Vagin, Greg KH, Linux Containers, Pavel Emelyanov, Oleg Nesterov, Al Viro, Andy Lutomirski, linux-api-u79uwXL29TY76Z2rM5mHXA, Cyrill Gorcunov, Michael Kerrisk, Thomas Gleixner, Linus Torvalds, Willy Tarreau, Andrey Vagin struct siginfo is a union and the kernel since 2.4 has been hiding a union tag in the high 16bits of si_code using the values: __SI_KILL __SI_TIMER __SI_POLL __SI_FAULT __SI_CHLD __SI_RT __SI_MESGQ __SI_SYS While this looks plausible on the surface, in practice this situation has not worked well. - Injected positive signals are not copied to user space properly unless they have these magic high bits set. - Injected positive signals are not reported properly by signalfd unless they have these magic high bits set. - These kernel internal values leaked to userspace via ptrace_peek_siginfo - It was possible to inject these kernel internal values and cause the the kernel to misbehave. - Kernel developers got confused and expected these kernel internal values in userspace in kernel self tests. - Kernel developers got confused and set si_code to __SI_FAULT which is SI_USER in userspace which causes userspace to think an ordinary user sent the signal and that it was not kernel generated. - The values make it impossible to reorganize the code to transform siginfo_copy_to_user into a plain copy_to_user. As si_code must be massaged before being passed to userspace. So remove these kernel internal si codes and make the kernel code simpler and more maintainable. To replace these kernel internal magic si_codes introduce the helper function siginfo_layout, that takes a signal number and an si_code and computes which union member of siginfo is being used. Have siginfo_layout return an enumeration so that gcc will have enough information to warn if a switch statement does not handle all of union members. A couple of architectures have a messed up ABI that defines signal specific duplications of SI_USER which causes more special cases in siginfo_layout than I would like. The good news is only problem architectures pay the cost. Update all of the code that used the previous magic __SI_ values to use the new SIL_ values and to call siginfo_layout to get those values. Escept where not all of the cases are handled remove the defaults in the switch statements so that if a new case is missed in the future the lack will show up at compile time. Modify the code that copies siginfo si_code to userspace to just copy the value and not cast si_code to a short first. The high bits are no longer used to hold a magic union member. Fixup the siginfo header files to stop including the __SI_ values in their constants and for the headers that were missing it to properly update the number of si_codes for each signal type. The fixes to copy_siginfo_from_user32 implementations has the interesting property that several of them perviously should never have worked as the __SI_ values they depended up where kernel internal. With that dependency gone those implementations should work much better. The idea of not passing the __SI_ values out to userspace and then not reinserting them has been tested with criu and criu worked without changes. Ref: 2.4.0-test1 Signed-off-by: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> --- arch/alpha/include/uapi/asm/siginfo.h | 4 +- arch/arm64/kernel/signal32.c | 23 +++---- arch/blackfin/include/uapi/asm/siginfo.h | 30 +++++--- arch/frv/include/uapi/asm/siginfo.h | 2 +- arch/ia64/include/uapi/asm/siginfo.h | 20 +++--- arch/ia64/kernel/signal.c | 17 +++-- arch/mips/include/uapi/asm/siginfo.h | 6 +- arch/mips/kernel/signal32.c | 19 +++-- arch/parisc/kernel/signal32.c | 31 ++++----- arch/powerpc/kernel/signal_32.c | 20 +++--- arch/s390/kernel/compat_signal.c | 32 ++++----- arch/sparc/include/uapi/asm/siginfo.h | 4 +- arch/sparc/kernel/signal32.c | 16 ++--- arch/tile/include/uapi/asm/siginfo.h | 4 +- arch/tile/kernel/compat_signal.c | 18 +++-- arch/tile/kernel/traps.c | 2 +- arch/x86/kernel/signal_compat.c | 21 +++--- fs/signalfd.c | 22 +++--- include/linux/signal.h | 14 ++++ include/uapi/asm-generic/siginfo.h | 115 +++++++++++++------------------ kernel/exit.c | 4 +- kernel/ptrace.c | 6 +- kernel/signal.c | 72 ++++++++++++++----- 23 files changed, 257 insertions(+), 245 deletions(-) diff --git a/arch/alpha/include/uapi/asm/siginfo.h b/arch/alpha/include/uapi/asm/siginfo.h index 972f547d9e41..70494d1d8f29 100644 --- a/arch/alpha/include/uapi/asm/siginfo.h +++ b/arch/alpha/include/uapi/asm/siginfo.h @@ -10,14 +10,14 @@ * SIGFPE si_codes */ #ifdef __KERNEL__ -#define FPE_FIXME (__SI_FAULT|0) /* Broken dup of SI_USER */ +#define FPE_FIXME 0 /* Broken dup of SI_USER */ #endif /* __KERNEL__ */ /* * SIGTRAP si_codes */ #ifdef __KERNEL__ -#define TRAP_FIXME (__SI_FAULT|0) /* Broken dup of SI_USER */ +#define TRAP_FIXME 0 /* Broken dup of SI_USER */ #endif /* __KERNEL__ */ #endif diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c index c747a0fc5d7d..9b95a935c21d 100644 --- a/arch/arm64/kernel/signal32.c +++ b/arch/arm64/kernel/signal32.c @@ -142,25 +142,25 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) */ err = __put_user(from->si_signo, &to->si_signo); err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); + err |= __put_user(from->si_code, &to->si_code); if (from->si_code < 0) err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); - else switch (from->si_code & __SI_MASK) { - case __SI_KILL: + else switch (siginfo_layout(from->si_signo, from->si_code)) { + case SIL_KILL: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); break; - case __SI_TIMER: + case SIL_TIMER: err |= __put_user(from->si_tid, &to->si_tid); err |= __put_user(from->si_overrun, &to->si_overrun); err |= __put_user(from->si_int, &to->si_int); break; - case __SI_POLL: + case SIL_POLL: err |= __put_user(from->si_band, &to->si_band); err |= __put_user(from->si_fd, &to->si_fd); break; - case __SI_FAULT: + case SIL_FAULT: err |= __put_user((compat_uptr_t)(unsigned long)from->si_addr, &to->si_addr); #ifdef BUS_MCEERR_AO @@ -173,29 +173,24 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb); #endif break; - case __SI_CHLD: + case SIL_CHLD: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_status, &to->si_status); err |= __put_user(from->si_utime, &to->si_utime); err |= __put_user(from->si_stime, &to->si_stime); break; - case __SI_RT: /* This is not generated by the kernel as of now. */ - case __SI_MESGQ: /* But this is */ + case SIL_RT: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_int, &to->si_int); break; - case __SI_SYS: + case SIL_SYS: err |= __put_user((compat_uptr_t)(unsigned long) from->si_call_addr, &to->si_call_addr); err |= __put_user(from->si_syscall, &to->si_syscall); err |= __put_user(from->si_arch, &to->si_arch); break; - default: /* this is just in case for now ... */ - err |= __put_user(from->si_pid, &to->si_pid); - err |= __put_user(from->si_uid, &to->si_uid); - break; } return err; } diff --git a/arch/blackfin/include/uapi/asm/siginfo.h b/arch/blackfin/include/uapi/asm/siginfo.h index c72f4e6e386f..79dfe3979123 100644 --- a/arch/blackfin/include/uapi/asm/siginfo.h +++ b/arch/blackfin/include/uapi/asm/siginfo.h @@ -14,28 +14,36 @@ #define si_uid16 _sifields._kill._uid -#define ILL_ILLPARAOP (__SI_FAULT|2) /* illegal opcode combine ********** */ -#define ILL_ILLEXCPT (__SI_FAULT|4) /* unrecoverable exception ********** */ -#define ILL_CPLB_VI (__SI_FAULT|9) /* D/I CPLB protect violation ******** */ -#define ILL_CPLB_MISS (__SI_FAULT|10) /* D/I CPLB miss ******** */ -#define ILL_CPLB_MULHIT (__SI_FAULT|11) /* D/I CPLB multiple hit ******** */ +#define ILL_ILLPARAOP 2 /* illegal opcode combine ********** */ +#define ILL_ILLEXCPT 4 /* unrecoverable exception ********** */ +#define ILL_CPLB_VI 9 /* D/I CPLB protect violation ******** */ +#define ILL_CPLB_MISS 10 /* D/I CPLB miss ******** */ +#define ILL_CPLB_MULHIT 11 /* D/I CPLB multiple hit ******** */ +#undef NSIGILL +#define NSIGILL 11 /* * SIGBUS si_codes */ -#define BUS_OPFETCH (__SI_FAULT|4) /* error from instruction fetch ******** */ +#define BUS_OPFETCH 4 /* error from instruction fetch ******** */ +#undef NSIGBUS +#define NSIGBUS 4 /* * SIGTRAP si_codes */ -#define TRAP_STEP (__SI_FAULT|1) /* single-step breakpoint************* */ -#define TRAP_TRACEFLOW (__SI_FAULT|2) /* trace buffer overflow ************* */ -#define TRAP_WATCHPT (__SI_FAULT|3) /* watchpoint match ************* */ -#define TRAP_ILLTRAP (__SI_FAULT|4) /* illegal trap ************* */ +#define TRAP_STEP 1 /* single-step breakpoint************* */ +#define TRAP_TRACEFLOW 2 /* trace buffer overflow ************* */ +#define TRAP_WATCHPT 3 /* watchpoint match ************* */ +#define TRAP_ILLTRAP 4 /* illegal trap ************* */ +#undef NSIGTRAP +#define NSIGTRAP 4 /* * SIGSEGV si_codes */ -#define SEGV_STACKFLOW (__SI_FAULT|3) /* stack overflow */ +#define SEGV_STACKFLOW 3 /* stack overflow */ +#undef NSIGSEGV +#define NSIGSEGV 3 #endif /* _UAPI_BFIN_SIGINFO_H */ diff --git a/arch/frv/include/uapi/asm/siginfo.h b/arch/frv/include/uapi/asm/siginfo.h index d3fd1ca45653..f55d9e0e9068 100644 --- a/arch/frv/include/uapi/asm/siginfo.h +++ b/arch/frv/include/uapi/asm/siginfo.h @@ -4,7 +4,7 @@ #include <linux/types.h> #include <asm-generic/siginfo.h> -#define FPE_MDAOVF (__SI_FAULT|9) /* media overflow */ +#define FPE_MDAOVF 9 /* media overflow */ #undef NSIGFPE #define NSIGFPE 9 diff --git a/arch/ia64/include/uapi/asm/siginfo.h b/arch/ia64/include/uapi/asm/siginfo.h index 3282f8b992fc..33389fc36f23 100644 --- a/arch/ia64/include/uapi/asm/siginfo.h +++ b/arch/ia64/include/uapi/asm/siginfo.h @@ -98,9 +98,9 @@ typedef struct siginfo { /* * SIGILL si_codes */ -#define ILL_BADIADDR (__SI_FAULT|9) /* unimplemented instruction address */ -#define __ILL_BREAK (__SI_FAULT|10) /* illegal break */ -#define __ILL_BNDMOD (__SI_FAULT|11) /* bundle-update (modification) in progress */ +#define ILL_BADIADDR 9 /* unimplemented instruction address */ +#define __ILL_BREAK 10 /* illegal break */ +#define __ILL_BNDMOD 11 /* bundle-update (modification) in progress */ #undef NSIGILL #define NSIGILL 11 @@ -108,20 +108,20 @@ typedef struct siginfo { * SIGFPE si_codes */ #ifdef __KERNEL__ -#define FPE_FIXME (__SI_FAULT|0) /* Broken dup of SI_USER */ +#define FPE_FIXME 0 /* Broken dup of SI_USER */ #endif /* __KERNEL__ */ -#define __FPE_DECOVF (__SI_FAULT|9) /* decimal overflow */ -#define __FPE_DECDIV (__SI_FAULT|10) /* decimal division by zero */ -#define __FPE_DECERR (__SI_FAULT|11) /* packed decimal error */ -#define __FPE_INVASC (__SI_FAULT|12) /* invalid ASCII digit */ -#define __FPE_INVDEC (__SI_FAULT|13) /* invalid decimal digit */ +#define __FPE_DECOVF 9 /* decimal overflow */ +#define __FPE_DECDIV 10 /* decimal division by zero */ +#define __FPE_DECERR 11 /* packed decimal error */ +#define __FPE_INVASC 12 /* invalid ASCII digit */ +#define __FPE_INVDEC 13 /* invalid decimal digit */ #undef NSIGFPE #define NSIGFPE 13 /* * SIGSEGV si_codes */ -#define __SEGV_PSTKOVF (__SI_FAULT|4) /* paragraph stack overflow */ +#define __SEGV_PSTKOVF 4 /* paragraph stack overflow */ #undef NSIGSEGV #define NSIGSEGV 4 diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 5db52c6813c4..6146d53b6ad7 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c @@ -124,31 +124,30 @@ copy_siginfo_to_user (siginfo_t __user *to, const siginfo_t *from) */ err = __put_user(from->si_signo, &to->si_signo); err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); - switch (from->si_code >> 16) { - case __SI_FAULT >> 16: + err |= __put_user(from->si_code, &to->si_code); + switch (siginfo_layout(from->si_signo, from->si_code)) { + case SIL_FAULT: err |= __put_user(from->si_flags, &to->si_flags); err |= __put_user(from->si_isr, &to->si_isr); - case __SI_POLL >> 16: + case SIL_POLL: err |= __put_user(from->si_addr, &to->si_addr); err |= __put_user(from->si_imm, &to->si_imm); break; - case __SI_TIMER >> 16: + case SIL_TIMER: err |= __put_user(from->si_tid, &to->si_tid); err |= __put_user(from->si_overrun, &to->si_overrun); err |= __put_user(from->si_ptr, &to->si_ptr); break; - case __SI_RT >> 16: /* Not generated by the kernel as of now. */ - case __SI_MESGQ >> 16: + case SIL_RT: err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_ptr, &to->si_ptr); break; - case __SI_CHLD >> 16: + case SIL_CHLD: err |= __put_user(from->si_utime, &to->si_utime); err |= __put_user(from->si_stime, &to->si_stime); err |= __put_user(from->si_status, &to->si_status); - default: + case SIL_KILL: err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_pid, &to->si_pid); break; diff --git a/arch/mips/include/uapi/asm/siginfo.h b/arch/mips/include/uapi/asm/siginfo.h index 9becfd102132..22a86d84a504 100644 --- a/arch/mips/include/uapi/asm/siginfo.h +++ b/arch/mips/include/uapi/asm/siginfo.h @@ -120,14 +120,14 @@ typedef struct siginfo { #undef SI_TIMER #undef SI_MESGQ #define SI_ASYNCIO -2 /* sent by AIO completion */ -#define SI_TIMER __SI_CODE(__SI_TIMER, -3) /* sent by timer expiration */ -#define SI_MESGQ __SI_CODE(__SI_MESGQ, -4) /* sent by real time mesq state change */ +#define SI_TIMER -3 /* sent by timer expiration */ +#define SI_MESGQ -4 /* sent by real time mesq state change */ /* * SIGFPE si_codes */ #ifdef __KERNEL__ -#define FPE_FIXME (__SI_FAULT|0) /* Broken dup of SI_USER */ +#define FPE_FIXME 0 /* Broken dup of SI_USER */ #endif /* __KERNEL__ */ #endif /* _UAPI_ASM_SIGINFO_H */ diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 84165f2b31ff..cf5c7c05e5a3 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -93,38 +93,37 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) at the same time. */ err = __put_user(from->si_signo, &to->si_signo); err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); + err |= __put_user(from->si_code, &to->si_code); if (from->si_code < 0) err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); else { - switch (from->si_code >> 16) { - case __SI_TIMER >> 16: + switch (siginfo_layout(from->si_signo, from->si_code)) { + case SIL_TIMER: err |= __put_user(from->si_tid, &to->si_tid); err |= __put_user(from->si_overrun, &to->si_overrun); err |= __put_user(from->si_int, &to->si_int); break; - case __SI_CHLD >> 16: + case SIL_CHLD: err |= __put_user(from->si_utime, &to->si_utime); err |= __put_user(from->si_stime, &to->si_stime); err |= __put_user(from->si_status, &to->si_status); - default: + case SIL_KILL: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); break; - case __SI_FAULT >> 16: + case SIL_FAULT: err |= __put_user((unsigned long)from->si_addr, &to->si_addr); break; - case __SI_POLL >> 16: + case SIL_POLL: err |= __put_user(from->si_band, &to->si_band); err |= __put_user(from->si_fd, &to->si_fd); break; - case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ - case __SI_MESGQ >> 16: + case SIL_RT: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_int, &to->si_int); break; - case __SI_SYS >> 16: + case SIL_SYS: err |= __copy_to_user(&to->si_call_addr, &from->si_call_addr, sizeof(compat_uptr_t)); err |= __put_user(from->si_syscall, &to->si_syscall); diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c index 70aaabb8b3cb..9e0cb6a577d6 100644 --- a/arch/parisc/kernel/signal32.c +++ b/arch/parisc/kernel/signal32.c @@ -290,25 +290,25 @@ copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from) if (to->si_code < 0) err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); else { - switch (to->si_code >> 16) { - case __SI_CHLD >> 16: + switch (siginfo_layout(to->si_signo, to->si_code)) { + case SIL_CHLD: err |= __get_user(to->si_utime, &from->si_utime); err |= __get_user(to->si_stime, &from->si_stime); err |= __get_user(to->si_status, &from->si_status); default: + case SIL_KILL: err |= __get_user(to->si_pid, &from->si_pid); err |= __get_user(to->si_uid, &from->si_uid); break; - case __SI_FAULT >> 16: + case SIL_FAULT: err |= __get_user(addr, &from->si_addr); to->si_addr = compat_ptr(addr); break; - case __SI_POLL >> 16: + case SIL_POLL: err |= __get_user(to->si_band, &from->si_band); err |= __get_user(to->si_fd, &from->si_fd); break; - case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ - case __SI_MESGQ >> 16: + case SIL_RT: err |= __get_user(to->si_pid, &from->si_pid); err |= __get_user(to->si_uid, &from->si_uid); err |= __get_user(to->si_int, &from->si_int); @@ -337,41 +337,40 @@ copy_siginfo_to_user32 (compat_siginfo_t __user *to, const siginfo_t *from) at the same time. */ err = __put_user(from->si_signo, &to->si_signo); err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); + err |= __put_user(from->si_code, &to->si_code); if (from->si_code < 0) err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); else { - switch (from->si_code >> 16) { - case __SI_CHLD >> 16: + switch (siginfo_layout(from->si_signo, from->si_code)) { + case SIL_CHLD: err |= __put_user(from->si_utime, &to->si_utime); err |= __put_user(from->si_stime, &to->si_stime); err |= __put_user(from->si_status, &to->si_status); - default: + case SIL_KILL: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); break; - case __SI_FAULT >> 16: + case SIL_FAULT: addr = ptr_to_compat(from->si_addr); err |= __put_user(addr, &to->si_addr); break; - case __SI_POLL >> 16: + case SIL_POLL: err |= __put_user(from->si_band, &to->si_band); err |= __put_user(from->si_fd, &to->si_fd); break; - case __SI_TIMER >> 16: + case SIL_TIMER: err |= __put_user(from->si_tid, &to->si_tid); err |= __put_user(from->si_overrun, &to->si_overrun); val = (compat_int_t)from->si_int; err |= __put_user(val, &to->si_int); break; - case __SI_RT >> 16: /* Not generated by the kernel as of now. */ - case __SI_MESGQ >> 16: + case SIL_RT: err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_pid, &to->si_pid); val = (compat_int_t)from->si_int; err |= __put_user(val, &to->si_int); break; - case __SI_SYS >> 16: + case SIL_SYS: err |= __put_user(ptr_to_compat(from->si_call_addr), &to->si_call_addr); err |= __put_user(from->si_syscall, &to->si_syscall); err |= __put_user(from->si_arch, &to->si_arch); diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 97bb1385e771..92fb1c8dbbd8 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -913,42 +913,40 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *d, const siginfo_t *s) */ err = __put_user(s->si_signo, &d->si_signo); err |= __put_user(s->si_errno, &d->si_errno); - err |= __put_user((short)s->si_code, &d->si_code); + err |= __put_user(s->si_code, &d->si_code); if (s->si_code < 0) err |= __copy_to_user(&d->_sifields._pad, &s->_sifields._pad, SI_PAD_SIZE32); - else switch(s->si_code >> 16) { - case __SI_CHLD >> 16: + else switch(siginfo_layout(s->si_signo, s->si_code)) { + case SIL_CHLD: err |= __put_user(s->si_pid, &d->si_pid); err |= __put_user(s->si_uid, &d->si_uid); err |= __put_user(s->si_utime, &d->si_utime); err |= __put_user(s->si_stime, &d->si_stime); err |= __put_user(s->si_status, &d->si_status); break; - case __SI_FAULT >> 16: + case SIL_FAULT: err |= __put_user((unsigned int)(unsigned long)s->si_addr, &d->si_addr); break; - case __SI_POLL >> 16: + case SIL_POLL: err |= __put_user(s->si_band, &d->si_band); err |= __put_user(s->si_fd, &d->si_fd); break; - case __SI_TIMER >> 16: + case SIL_TIMER: err |= __put_user(s->si_tid, &d->si_tid); err |= __put_user(s->si_overrun, &d->si_overrun); err |= __put_user(s->si_int, &d->si_int); break; - case __SI_SYS >> 16: + case SIL_SYS: err |= __put_user(ptr_to_compat(s->si_call_addr), &d->si_call_addr); err |= __put_user(s->si_syscall, &d->si_syscall); err |= __put_user(s->si_arch, &d->si_arch); break; - case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ - case __SI_MESGQ >> 16: + case SIL_RT: err |= __put_user(s->si_int, &d->si_int); /* fallthrough */ - case __SI_KILL >> 16: - default: + case SIL_KILL: err |= __put_user(s->si_pid, &d->si_pid); err |= __put_user(s->si_uid, &d->si_uid); break; diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index c620049c61f2..f549c4657376 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -75,35 +75,34 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) at the same time. */ err = __put_user(from->si_signo, &to->si_signo); err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); + err |= __put_user(from->si_code, &to->si_code); if (from->si_code < 0) err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); else { - switch (from->si_code >> 16) { - case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ - case __SI_MESGQ >> 16: + switch (siginfo_layout(from->si_signo, from->si_code)) { + case SIL_RT: err |= __put_user(from->si_int, &to->si_int); /* fallthrough */ - case __SI_KILL >> 16: + case SIL_KILL: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); break; - case __SI_CHLD >> 16: + case SIL_CHLD: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_utime, &to->si_utime); err |= __put_user(from->si_stime, &to->si_stime); err |= __put_user(from->si_status, &to->si_status); break; - case __SI_FAULT >> 16: + case SIL_FAULT: err |= __put_user((unsigned long) from->si_addr, &to->si_addr); break; - case __SI_POLL >> 16: + case SIL_POLL: err |= __put_user(from->si_band, &to->si_band); err |= __put_user(from->si_fd, &to->si_fd); break; - case __SI_TIMER >> 16: + case SIL_TIMER: err |= __put_user(from->si_tid, &to->si_tid); err |= __put_user(from->si_overrun, &to->si_overrun); err |= __put_user(from->si_int, &to->si_int); @@ -127,32 +126,31 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) if (to->si_code < 0) err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); else { - switch (to->si_code >> 16) { - case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ - case __SI_MESGQ >> 16: + switch (siginfo_layout(to->si_signo, to->si_code)) { + case SIL_RT: err |= __get_user(to->si_int, &from->si_int); /* fallthrough */ - case __SI_KILL >> 16: + case SIL_KILL: err |= __get_user(to->si_pid, &from->si_pid); err |= __get_user(to->si_uid, &from->si_uid); break; - case __SI_CHLD >> 16: + case SIL_CHLD: err |= __get_user(to->si_pid, &from->si_pid); err |= __get_user(to->si_uid, &from->si_uid); err |= __get_user(to->si_utime, &from->si_utime); err |= __get_user(to->si_stime, &from->si_stime); err |= __get_user(to->si_status, &from->si_status); break; - case __SI_FAULT >> 16: + case SIL_FAULT: err |= __get_user(tmp, &from->si_addr); to->si_addr = (void __force __user *) (u64) (tmp & PSW32_ADDR_INSN); break; - case __SI_POLL >> 16: + case SIL_POLL: err |= __get_user(to->si_band, &from->si_band); err |= __get_user(to->si_fd, &from->si_fd); break; - case __SI_TIMER >> 16: + case SIL_TIMER: err |= __get_user(to->si_tid, &from->si_tid); err |= __get_user(to->si_overrun, &from->si_overrun); err |= __get_user(to->si_int, &from->si_int); diff --git a/arch/sparc/include/uapi/asm/siginfo.h b/arch/sparc/include/uapi/asm/siginfo.h index da2126e0c536..157f46fe374f 100644 --- a/arch/sparc/include/uapi/asm/siginfo.h +++ b/arch/sparc/include/uapi/asm/siginfo.h @@ -20,13 +20,13 @@ * SIGFPE si_codes */ #ifdef __KERNEL__ -#define FPE_FIXME (__SI_FAULT|0) /* Broken dup of SI_USER */ +#define FPE_FIXME 0 /* Broken dup of SI_USER */ #endif /* __KERNEL__ */ /* * SIGEMT si_codes */ -#define EMT_TAGOVF (__SI_FAULT|1) /* tag overflow */ +#define EMT_TAGOVF 1 /* tag overflow */ #define NSIGEMT 1 #endif /* _UAPI__SPARC_SIGINFO_H */ diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index b4096bb665b2..0e4c08c45a37 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -85,34 +85,34 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) at the same time. */ err = __put_user(from->si_signo, &to->si_signo); err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); + err |= __put_user(from->si_code, &to->si_code); if (from->si_code < 0) err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); else { - switch (from->si_code >> 16) { - case __SI_TIMER >> 16: + switch (siginfo_layout(from->si_signo, from->si_code)) { + case SIL_TIMER: err |= __put_user(from->si_tid, &to->si_tid); err |= __put_user(from->si_overrun, &to->si_overrun); err |= __put_user(from->si_int, &to->si_int); break; - case __SI_CHLD >> 16: + case SIL_CHLD: err |= __put_user(from->si_utime, &to->si_utime); err |= __put_user(from->si_stime, &to->si_stime); err |= __put_user(from->si_status, &to->si_status); default: + case SIL_KILL: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); break; - case __SI_FAULT >> 16: + case SIL_FAULT: err |= __put_user(from->si_trapno, &to->si_trapno); err |= __put_user((unsigned long)from->si_addr, &to->si_addr); break; - case __SI_POLL >> 16: + case SIL_POLL: err |= __put_user(from->si_band, &to->si_band); err |= __put_user(from->si_fd, &to->si_fd); break; - case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ - case __SI_MESGQ >> 16: + case SIL_RT: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_int, &to->si_int); diff --git a/arch/tile/include/uapi/asm/siginfo.h b/arch/tile/include/uapi/asm/siginfo.h index 56d661bb010b..e83f931aa1f0 100644 --- a/arch/tile/include/uapi/asm/siginfo.h +++ b/arch/tile/include/uapi/asm/siginfo.h @@ -26,8 +26,8 @@ /* * Additional Tile-specific SIGILL si_codes */ -#define ILL_DBLFLT (__SI_FAULT|9) /* double fault */ -#define ILL_HARDWALL (__SI_FAULT|10) /* user networks hardwall violation */ +#define ILL_DBLFLT 9 /* double fault */ +#define ILL_HARDWALL 10 /* user networks hardwall violation */ #undef NSIGILL #define NSIGILL 10 diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c index 0e863f1ee08c..971d87a1d8cf 100644 --- a/arch/tile/kernel/compat_signal.c +++ b/arch/tile/kernel/compat_signal.c @@ -64,7 +64,7 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *fr 3 ints plus the relevant union member. */ err = __put_user(from->si_signo, &to->si_signo); err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); + err |= __put_user(from->si_code, &to->si_code); if (from->si_code < 0) { err |= __put_user(from->si_pid, &to->si_pid); @@ -77,28 +77,26 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *fr */ err |= __put_user(from->_sifields._pad[0], &to->_sifields._pad[0]); - switch (from->si_code >> 16) { - case __SI_FAULT >> 16: + switch (siginfo_layout(from->si_signo, from->si_code)) { + case SIL_FAULT: break; - case __SI_CHLD >> 16: + case SIL_CHLD: err |= __put_user(from->si_utime, &to->si_utime); err |= __put_user(from->si_stime, &to->si_stime); err |= __put_user(from->si_status, &to->si_status); /* FALL THROUGH */ default: - case __SI_KILL >> 16: + case SIL_KILL: err |= __put_user(from->si_uid, &to->si_uid); break; - case __SI_POLL >> 16: + case SIL_POLL: err |= __put_user(from->si_fd, &to->si_fd); break; - case __SI_TIMER >> 16: + case SIL_TIMER: err |= __put_user(from->si_overrun, &to->si_overrun); err |= __put_user(from->si_int, &to->si_int); break; - /* This is not generated by the kernel as of now. */ - case __SI_RT >> 16: - case __SI_MESGQ >> 16: + case SIL_RT: err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_int, &to->si_int); break; diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c index 54804866f238..9b08c6055f15 100644 --- a/arch/tile/kernel/traps.c +++ b/arch/tile/kernel/traps.c @@ -188,7 +188,7 @@ static int special_ill(tile_bundle_bits bundle, int *sigp, int *codep) /* Make it the requested signal. */ *sigp = sig; - *codep = code | __SI_FAULT; + *codep = code; return 1; } diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c index 71beb28600d4..ab9feb5887b1 100644 --- a/arch/x86/kernel/signal_compat.c +++ b/arch/x86/kernel/signal_compat.c @@ -129,7 +129,7 @@ int __copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from, 3 ints plus the relevant union member. */ put_user_ex(from->si_signo, &to->si_signo); put_user_ex(from->si_errno, &to->si_errno); - put_user_ex((short)from->si_code, &to->si_code); + put_user_ex(from->si_code, &to->si_code); if (from->si_code < 0) { put_user_ex(from->si_pid, &to->si_pid); @@ -142,8 +142,8 @@ int __copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from, */ put_user_ex(from->_sifields._pad[0], &to->_sifields._pad[0]); - switch (from->si_code >> 16) { - case __SI_FAULT >> 16: + switch (siginfo_layout(from->si_signo, from->si_code)) { + case SIL_FAULT: if (from->si_signo == SIGBUS && (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)) @@ -160,11 +160,11 @@ int __copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from, put_user_ex(from->si_pkey, &to->si_pkey); } break; - case __SI_SYS >> 16: + case SIL_SYS: put_user_ex(from->si_syscall, &to->si_syscall); put_user_ex(from->si_arch, &to->si_arch); break; - case __SI_CHLD >> 16: + case SIL_CHLD: if (!x32_ABI) { put_user_ex(from->si_utime, &to->si_utime); put_user_ex(from->si_stime, &to->si_stime); @@ -174,21 +174,18 @@ int __copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from, } put_user_ex(from->si_status, &to->si_status); /* FALL THROUGH */ - default: - case __SI_KILL >> 16: + case SIL_KILL: put_user_ex(from->si_uid, &to->si_uid); break; - case __SI_POLL >> 16: + case SIL_POLL: put_user_ex(from->si_fd, &to->si_fd); break; - case __SI_TIMER >> 16: + case SIL_TIMER: put_user_ex(from->si_overrun, &to->si_overrun); put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr); break; - /* This is not generated by the kernel as of now. */ - case __SI_RT >> 16: - case __SI_MESGQ >> 16: + case SIL_RT: put_user_ex(from->si_uid, &to->si_uid); put_user_ex(from->si_int, &to->si_int); break; diff --git a/fs/signalfd.c b/fs/signalfd.c index 593b022ac11b..d2c434112f42 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c @@ -95,23 +95,23 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, */ err |= __put_user(kinfo->si_signo, &uinfo->ssi_signo); err |= __put_user(kinfo->si_errno, &uinfo->ssi_errno); - err |= __put_user((short) kinfo->si_code, &uinfo->ssi_code); - switch (kinfo->si_code & __SI_MASK) { - case __SI_KILL: + err |= __put_user(kinfo->si_code, &uinfo->ssi_code); + switch (siginfo_layout(kinfo->si_signo, kinfo->si_code)) { + case SIL_KILL: err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid); err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid); break; - case __SI_TIMER: + case SIL_TIMER: err |= __put_user(kinfo->si_tid, &uinfo->ssi_tid); err |= __put_user(kinfo->si_overrun, &uinfo->ssi_overrun); err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr); err |= __put_user(kinfo->si_int, &uinfo->ssi_int); break; - case __SI_POLL: + case SIL_POLL: err |= __put_user(kinfo->si_band, &uinfo->ssi_band); err |= __put_user(kinfo->si_fd, &uinfo->ssi_fd); break; - case __SI_FAULT: + case SIL_FAULT: err |= __put_user((long) kinfo->si_addr, &uinfo->ssi_addr); #ifdef __ARCH_SI_TRAPNO err |= __put_user(kinfo->si_trapno, &uinfo->ssi_trapno); @@ -128,20 +128,14 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, &uinfo->ssi_addr_lsb); #endif break; - case __SI_CHLD: + case SIL_CHLD: err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid); err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid); err |= __put_user(kinfo->si_status, &uinfo->ssi_status); err |= __put_user(kinfo->si_utime, &uinfo->ssi_utime); err |= __put_user(kinfo->si_stime, &uinfo->ssi_stime); break; - case __SI_RT: /* This is not generated by the kernel as of now. */ - case __SI_MESGQ: /* But this is */ - err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid); - err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid); - err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr); - err |= __put_user(kinfo->si_int, &uinfo->ssi_int); - break; + case SIL_RT: default: /* * This case catches also the signals queued by sigqueue(). diff --git a/include/linux/signal.h b/include/linux/signal.h index c97cc20369c0..38564e3e54c7 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -21,6 +21,20 @@ static inline void copy_siginfo(struct siginfo *to, struct siginfo *from) int copy_siginfo_to_user(struct siginfo __user *to, const struct siginfo *from); +enum siginfo_layout { + SIL_KILL, + SIL_TIMER, + SIL_POLL, + SIL_FAULT, + SIL_CHLD, + SIL_RT, +#ifdef __ARCH_SIGSYS + SIL_SYS, +#endif +}; + +enum siginfo_layout siginfo_layout(int sig, int si_code); + /* * Define some primitives to manipulate sigset_t. */ diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h index 9e956ea94d57..e5aa6794cea4 100644 --- a/include/uapi/asm-generic/siginfo.h +++ b/include/uapi/asm-generic/siginfo.h @@ -151,29 +151,6 @@ typedef struct siginfo { #define si_arch _sifields._sigsys._arch #endif -#ifdef __KERNEL__ -#define __SI_MASK 0xffff0000u -#define __SI_KILL (0 << 16) -#define __SI_TIMER (1 << 16) -#define __SI_POLL (2 << 16) -#define __SI_FAULT (3 << 16) -#define __SI_CHLD (4 << 16) -#define __SI_RT (5 << 16) -#define __SI_MESGQ (6 << 16) -#define __SI_SYS (7 << 16) -#define __SI_CODE(T,N) ((T) | ((N) & 0xffff)) -#else /* __KERNEL__ */ -#define __SI_KILL 0 -#define __SI_TIMER 0 -#define __SI_POLL 0 -#define __SI_FAULT 0 -#define __SI_CHLD 0 -#define __SI_RT 0 -#define __SI_MESGQ 0 -#define __SI_SYS 0 -#define __SI_CODE(T,N) (N) -#endif /* __KERNEL__ */ - /* * si_code values * Digital reserves positive values for kernel-generated signals. @@ -181,10 +158,10 @@ typedef struct siginfo { #define SI_USER 0 /* sent by kill, sigsend, raise */ #define SI_KERNEL 0x80 /* sent by the kernel from somewhere */ #define SI_QUEUE -1 /* sent by sigqueue */ -#define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */ -#define SI_MESGQ __SI_CODE(__SI_MESGQ,-3) /* sent by real time mesq state change */ +#define SI_TIMER -2 /* sent by timer expiration */ +#define SI_MESGQ -3 /* sent by real time mesq state change */ #define SI_ASYNCIO -4 /* sent by AIO completion */ -#define SI_SIGIO __SI_CODE(__SI_POLL,-5) /* sent by queued SIGIO */ +#define SI_SIGIO -5 /* sent by queued SIGIO */ #define SI_TKILL -6 /* sent by tkill system call */ #define SI_DETHREAD -7 /* sent by execve() killing subsidiary threads */ @@ -194,86 +171,86 @@ typedef struct siginfo { /* * SIGILL si_codes */ -#define ILL_ILLOPC (__SI_FAULT|1) /* illegal opcode */ -#define ILL_ILLOPN (__SI_FAULT|2) /* illegal operand */ -#define ILL_ILLADR (__SI_FAULT|3) /* illegal addressing mode */ -#define ILL_ILLTRP (__SI_FAULT|4) /* illegal trap */ -#define ILL_PRVOPC (__SI_FAULT|5) /* privileged opcode */ -#define ILL_PRVREG (__SI_FAULT|6) /* privileged register */ -#define ILL_COPROC (__SI_FAULT|7) /* coprocessor error */ -#define ILL_BADSTK (__SI_FAULT|8) /* internal stack error */ +#define ILL_ILLOPC 1 /* illegal opcode */ +#define ILL_ILLOPN 2 /* illegal operand */ +#define ILL_ILLADR 3 /* illegal addressing mode */ +#define ILL_ILLTRP 4 /* illegal trap */ +#define ILL_PRVOPC 5 /* privileged opcode */ +#define ILL_PRVREG 6 /* privileged register */ +#define ILL_COPROC 7 /* coprocessor error */ +#define ILL_BADSTK 8 /* internal stack error */ #define NSIGILL 8 /* * SIGFPE si_codes */ -#define FPE_INTDIV (__SI_FAULT|1) /* integer divide by zero */ -#define FPE_INTOVF (__SI_FAULT|2) /* integer overflow */ -#define FPE_FLTDIV (__SI_FAULT|3) /* floating point divide by zero */ -#define FPE_FLTOVF (__SI_FAULT|4) /* floating point overflow */ -#define FPE_FLTUND (__SI_FAULT|5) /* floating point underflow */ -#define FPE_FLTRES (__SI_FAULT|6) /* floating point inexact result */ -#define FPE_FLTINV (__SI_FAULT|7) /* floating point invalid operation */ -#define FPE_FLTSUB (__SI_FAULT|8) /* subscript out of range */ +#define FPE_INTDIV 1 /* integer divide by zero */ +#define FPE_INTOVF 2 /* integer overflow */ +#define FPE_FLTDIV 3 /* floating point divide by zero */ +#define FPE_FLTOVF 4 /* floating point overflow */ +#define FPE_FLTUND 5 /* floating point underflow */ +#define FPE_FLTRES 6 /* floating point inexact result */ +#define FPE_FLTINV 7 /* floating point invalid operation */ +#define FPE_FLTSUB 8 /* subscript out of range */ #define NSIGFPE 8 /* * SIGSEGV si_codes */ -#define SEGV_MAPERR (__SI_FAULT|1) /* address not mapped to object */ -#define SEGV_ACCERR (__SI_FAULT|2) /* invalid permissions for mapped object */ -#define SEGV_BNDERR (__SI_FAULT|3) /* failed address bound checks */ -#define SEGV_PKUERR (__SI_FAULT|4) /* failed protection key checks */ +#define SEGV_MAPERR 1 /* address not mapped to object */ +#define SEGV_ACCERR 2 /* invalid permissions for mapped object */ +#define SEGV_BNDERR 3 /* failed address bound checks */ +#define SEGV_PKUERR 4 /* failed protection key checks */ #define NSIGSEGV 4 /* * SIGBUS si_codes */ -#define BUS_ADRALN (__SI_FAULT|1) /* invalid address alignment */ -#define BUS_ADRERR (__SI_FAULT|2) /* non-existent physical address */ -#define BUS_OBJERR (__SI_FAULT|3) /* object specific hardware error */ +#define BUS_ADRALN 1 /* invalid address alignment */ +#define BUS_ADRERR 2 /* non-existent physical address */ +#define BUS_OBJERR 3 /* object specific hardware error */ /* hardware memory error consumed on a machine check: action required */ -#define BUS_MCEERR_AR (__SI_FAULT|4) +#define BUS_MCEERR_AR 4 /* hardware memory error detected in process but not consumed: action optional*/ -#define BUS_MCEERR_AO (__SI_FAULT|5) +#define BUS_MCEERR_AO 5 #define NSIGBUS 5 /* * SIGTRAP si_codes */ -#define TRAP_BRKPT (__SI_FAULT|1) /* process breakpoint */ -#define TRAP_TRACE (__SI_FAULT|2) /* process trace trap */ -#define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */ -#define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint/watchpoint */ +#define TRAP_BRKPT 1 /* process breakpoint */ +#define TRAP_TRACE 2 /* process trace trap */ +#define TRAP_BRANCH 3 /* process taken branch trap */ +#define TRAP_HWBKPT 4 /* hardware breakpoint/watchpoint */ #define NSIGTRAP 4 /* * SIGCHLD si_codes */ -#define CLD_EXITED (__SI_CHLD|1) /* child has exited */ -#define CLD_KILLED (__SI_CHLD|2) /* child was killed */ -#define CLD_DUMPED (__SI_CHLD|3) /* child terminated abnormally */ -#define CLD_TRAPPED (__SI_CHLD|4) /* traced child has trapped */ -#define CLD_STOPPED (__SI_CHLD|5) /* child has stopped */ -#define CLD_CONTINUED (__SI_CHLD|6) /* stopped child has continued */ +#define CLD_EXITED 1 /* child has exited */ +#define CLD_KILLED 2 /* child was killed */ +#define CLD_DUMPED 3 /* child terminated abnormally */ +#define CLD_TRAPPED 4 /* traced child has trapped */ +#define CLD_STOPPED 5 /* child has stopped */ +#define CLD_CONTINUED 6 /* stopped child has continued */ #define NSIGCHLD 6 /* * SIGPOLL (or any other signal without signal specific si_codes) si_codes */ -#define POLL_IN (__SI_POLL|1) /* data input available */ -#define POLL_OUT (__SI_POLL|2) /* output buffers available */ -#define POLL_MSG (__SI_POLL|3) /* input message available */ -#define POLL_ERR (__SI_POLL|4) /* i/o error */ -#define POLL_PRI (__SI_POLL|5) /* high priority input available */ -#define POLL_HUP (__SI_POLL|6) /* device disconnected */ +#define POLL_IN 1 /* data input available */ +#define POLL_OUT 2 /* output buffers available */ +#define POLL_MSG 3 /* input message available */ +#define POLL_ERR 4 /* i/o error */ +#define POLL_PRI 5 /* high priority input available */ +#define POLL_HUP 6 /* device disconnected */ #define NSIGPOLL 6 /* * SIGSYS si_codes */ -#define SYS_SECCOMP (__SI_SYS|1) /* seccomp triggered */ -#define NSIGSYS 1 +#define SYS_SECCOMP 1 /* seccomp triggered */ +#define NSIGSYS 1 /* * sigevent definitions diff --git a/kernel/exit.c b/kernel/exit.c index c5548faa9f37..c8f23613df5b 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -1616,7 +1616,7 @@ SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *, user_access_begin(); unsafe_put_user(signo, &infop->si_signo, Efault); unsafe_put_user(0, &infop->si_errno, Efault); - unsafe_put_user((short)info.cause, &infop->si_code, Efault); + unsafe_put_user(info.cause, &infop->si_code, Efault); unsafe_put_user(info.pid, &infop->si_pid, Efault); unsafe_put_user(info.uid, &infop->si_uid, Efault); unsafe_put_user(info.status, &infop->si_status, Efault); @@ -1742,7 +1742,7 @@ COMPAT_SYSCALL_DEFINE5(waitid, user_access_begin(); unsafe_put_user(signo, &infop->si_signo, Efault); unsafe_put_user(0, &infop->si_errno, Efault); - unsafe_put_user((short)info.cause, &infop->si_code, Efault); + unsafe_put_user(info.cause, &infop->si_code, Efault); unsafe_put_user(info.pid, &infop->si_pid, Efault); unsafe_put_user(info.uid, &infop->si_uid, Efault); unsafe_put_user(info.status, &infop->si_status, Efault); diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 60f356d91060..84b1367935e4 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -728,8 +728,7 @@ static int ptrace_peek_siginfo(struct task_struct *child, if (unlikely(in_compat_syscall())) { compat_siginfo_t __user *uinfo = compat_ptr(data); - if (copy_siginfo_to_user32(uinfo, &info) || - __put_user(info.si_code, &uinfo->si_code)) { + if (copy_siginfo_to_user32(uinfo, &info)) { ret = -EFAULT; break; } @@ -739,8 +738,7 @@ static int ptrace_peek_siginfo(struct task_struct *child, { siginfo_t __user *uinfo = (siginfo_t __user *) data; - if (copy_siginfo_to_user(uinfo, &info) || - __put_user(info.si_code, &uinfo->si_code)) { + if (copy_siginfo_to_user(uinfo, &info)) { ret = -EFAULT; break; } diff --git a/kernel/signal.c b/kernel/signal.c index caed9133ae52..6bd53c8189f0 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2682,6 +2682,51 @@ COMPAT_SYSCALL_DEFINE2(rt_sigpending, compat_sigset_t __user *, uset, } #endif +enum siginfo_layout siginfo_layout(int sig, int si_code) +{ + enum siginfo_layout layout = SIL_KILL; + if ((si_code > SI_USER) && (si_code < SI_KERNEL)) { + static const struct { + unsigned char limit, layout; + } filter[] = { + [SIGILL] = { NSIGILL, SIL_FAULT }, + [SIGFPE] = { NSIGFPE, SIL_FAULT }, + [SIGSEGV] = { NSIGSEGV, SIL_FAULT }, + [SIGBUS] = { NSIGBUS, SIL_FAULT }, + [SIGTRAP] = { NSIGTRAP, SIL_FAULT }, +#if defined(SIGMET) && defined(NSIGEMT) + [SIGEMT] = { NSIGEMT, SIL_FAULT }, +#endif + [SIGCHLD] = { NSIGCHLD, SIL_CHLD }, + [SIGPOLL] = { NSIGPOLL, SIL_POLL }, +#ifdef __ARCH_SIGSYS + [SIGSYS] = { NSIGSYS, SIL_SYS }, +#endif + }; + if ((sig < ARRAY_SIZE(filter)) && (si_code <= filter[sig].limit)) + layout = filter[sig].layout; + else if (si_code <= NSIGPOLL) + layout = SIL_POLL; + } else { + if (si_code == SI_TIMER) + layout = SIL_TIMER; + else if (si_code == SI_SIGIO) + layout = SIL_POLL; + else if (si_code < 0) + layout = SIL_RT; + /* Tests to support buggy kernel ABIs */ +#ifdef TRAP_FIXME + if ((sig == SIGTRAP) && (si_code == TRAP_FIXME)) + layout = SIL_FAULT; +#endif +#ifdef FPE_FIXME + if ((sig == SIGFPE) && (si_code == FPE_FIXME)) + layout = SIL_FAULT; +#endif + } + return layout; +} + #ifndef HAVE_ARCH_COPY_SIGINFO_TO_USER int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from) @@ -2704,22 +2749,20 @@ int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from) */ err = __put_user(from->si_signo, &to->si_signo); err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); - switch (from->si_code & __SI_MASK) { - case __SI_KILL: + err |= __put_user(from->si_code, &to->si_code); + switch (siginfo_layout(from->si_signo, from->si_code)) { + case SIL_KILL: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); break; - case __SI_TIMER: - err |= __put_user(from->si_tid, &to->si_tid); - err |= __put_user(from->si_overrun, &to->si_overrun); - err |= __put_user(from->si_ptr, &to->si_ptr); + case SIL_TIMER: + /* Unreached SI_TIMER is negative */ break; - case __SI_POLL: + case SIL_POLL: err |= __put_user(from->si_band, &to->si_band); err |= __put_user(from->si_fd, &to->si_fd); break; - case __SI_FAULT: + case SIL_FAULT: err |= __put_user(from->si_addr, &to->si_addr); #ifdef __ARCH_SI_TRAPNO err |= __put_user(from->si_trapno, &to->si_trapno); @@ -2744,30 +2787,25 @@ int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from) err |= __put_user(from->si_pkey, &to->si_pkey); #endif break; - case __SI_CHLD: + case SIL_CHLD: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_status, &to->si_status); err |= __put_user(from->si_utime, &to->si_utime); err |= __put_user(from->si_stime, &to->si_stime); break; - case __SI_RT: /* This is not generated by the kernel as of now. */ - case __SI_MESGQ: /* But this is */ + case SIL_RT: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_ptr, &to->si_ptr); break; #ifdef __ARCH_SIGSYS - case __SI_SYS: + case SIL_SYS: err |= __put_user(from->si_call_addr, &to->si_call_addr); err |= __put_user(from->si_syscall, &to->si_syscall); err |= __put_user(from->si_arch, &to->si_arch); break; #endif - default: /* this is just in case for now ... */ - err |= __put_user(from->si_pid, &to->si_pid); - err |= __put_user(from->si_uid, &to->si_uid); - break; } return err; } -- 2.10.1 ^ permalink raw reply related [flat|nested] 24+ messages in thread
[parent not found: <20170718140651.15973-7-ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>]
* Re: [PATCH 7/7] signal: Remove kernel interal si_code magic [not found] ` <20170718140651.15973-7-ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> @ 2017-07-18 16:57 ` Linus Torvalds [not found] ` <CA+55aFyKsmf+BpYjcH30MGpHTDJ=zgYPx6kwyEB9CXXFxj_xsw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 24+ messages in thread From: Linus Torvalds @ 2017-07-18 16:57 UTC (permalink / raw) To: Eric W. Biederman Cc: Linux Kernel Mailing List, Andy Lutomirski, Al Viro, Oleg Nesterov, Andrei Vagin, Thomas Gleixner, Greg KH, Andrey Vagin, Serge Hallyn, Pavel Emelyanov, Cyrill Gorcunov, Peter Zijlstra, Willy Tarreau, linux-arch-u79uwXL29TY76Z2rM5mHXA, Linux API, Linux Containers, Michael Kerrisk On Tue, Jul 18, 2017 at 7:06 AM, Eric W. Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> wrote: > struct siginfo is a union and the kernel since 2.4 has been hiding a union > tag in the high 16bits of si_code using the values: > __SI_KILL > __SI_TIMER > __SI_POLL > __SI_FAULT > __SI_CHLD > __SI_RT > __SI_MESGQ > __SI_SYS > > While this looks plausible on the surface, in practice this situation has > not worked well. So on the whole I think we just need to do this, but the part I really hate about this series is still this the siginfo_layout() part. I can well believe that it is needed for the compat case. siginfo is a piece of crap crazy type, and re-ordering fields for compat is something we are always going to have to do. But for the native case, the *only* reason we do not just copy the siginfo as-is seems to be that it's just too big, due to other bad design decisions in siginfo ("let's make sure it's big enough by allocating 512 bytes for it). And afaik, absolutely nobody uses more than about 36 bytes of that 512-byte _sifields union (and that one use is SIGILL with three pointers and three integers and some padding. So why don't we just say "screw this idiotic layout crap, and just unconditionally copy that much smaller maximum of bytes"? Leave that layout thing purely for compat handling. Yes, yes, there's a couple of small gotchas's: - "_sys_private" for posix timers, and it would have to be moved to the end of the structure so that it doesn't get copied. - make sure those 36 bytes are cleared when allocating the siginfo (this should be trivial) so that we don't leak any other memory. But on the whole, it looks pretty straightforward to just get rid of those stupid layout things, and make them purely about compat stuff. Please? The si_code stuff clearly needs to be done regardless, so much of this patch series looks good to me. But if we're doign this cleanup, can't we please go that one extra step and get rid of the crazy "let's treat the union as different types", and just treat it as a largely opaque thing. Pretty please? Linus ^ permalink raw reply [flat|nested] 24+ messages in thread
[parent not found: <CA+55aFyKsmf+BpYjcH30MGpHTDJ=zgYPx6kwyEB9CXXFxj_xsw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: [PATCH 7/7] signal: Remove kernel interal si_code magic [not found] ` <CA+55aFyKsmf+BpYjcH30MGpHTDJ=zgYPx6kwyEB9CXXFxj_xsw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2017-07-18 17:27 ` Eric W. Biederman [not found] ` <878tjlbqpt.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> 0 siblings, 1 reply; 24+ messages in thread From: Eric W. Biederman @ 2017-07-18 17:27 UTC (permalink / raw) To: Linus Torvalds Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Andrei Vagin, Greg KH, Linux Containers, Pavel Emelyanov, Oleg Nesterov, Linux Kernel Mailing List, Al Viro, Andy Lutomirski, Linux API, Cyrill Gorcunov, Michael Kerrisk, Thomas Gleixner, Willy Tarreau, Andrey Vagin Linus Torvalds <torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org> writes: > On Tue, Jul 18, 2017 at 7:06 AM, Eric W. Biederman > <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> wrote: >> struct siginfo is a union and the kernel since 2.4 has been hiding a union >> tag in the high 16bits of si_code using the values: >> __SI_KILL >> __SI_TIMER >> __SI_POLL >> __SI_FAULT >> __SI_CHLD >> __SI_RT >> __SI_MESGQ >> __SI_SYS >> >> While this looks plausible on the surface, in practice this situation has >> not worked well. > > So on the whole I think we just need to do this, but the part I really > hate about this series is still this the siginfo_layout() part. > > I can well believe that it is needed for the compat case. siginfo is a > piece of crap crazy type, and re-ordering fields for compat is > something we are always going to have to do. > > But for the native case, the *only* reason we do not just copy the > siginfo as-is seems to be that it's just too big, due to other bad > design decisions in siginfo ("let's make sure it's big enough by > allocating 512 bytes for it). > > And afaik, absolutely nobody uses more than about 36 bytes of that > 512-byte _sifields union (and that one use is SIGILL with three > pointers and three integers and some padding. > > So why don't we just say "screw this idiotic layout crap, and just > unconditionally copy that much smaller maximum of bytes"? > > Leave that layout thing purely for compat handling. I completely agree. > Yes, yes, there's a couple of small gotchas's: > > - "_sys_private" for posix timers, and it would have to be moved to > the end of the structure so that it doesn't get copied. I don't think we actually need _sys_private at all. I think the best solution would involve embedding struct siginfo into struct k_itimer (as we always allocate one). Then we can just perform container_of on the siginfo and look at the k_itimer instead. > - make sure those 36 bytes are cleared when allocating the siginfo > (this should be trivial) so that we don't leak any other memory. > > But on the whole, it looks pretty straightforward to just get rid of > those stupid layout things, and make them purely about compat stuff. > > Please? > > The si_code stuff clearly needs to be done regardless, so much of this > patch series looks good to me. But if we're doign this cleanup, can't > we please go that one extra step and get rid of the crazy "let's treat > the union as different types", and just treat it as a largely opaque > thing. > > Pretty please? That is my next step. I have started on it but it is a big additional patch. I have to insert a bunch of memsets to ensure we are not copying unitialized stack contents to userspace. I have been convinced not to expect any performance issues: - Worst case two reads from memory 60ns*2 = 120ns. - 650ns time to send a signal. - 350ns time to receive a signal. So that is maybe a 10% change, and more likely lost completely in the noise. I intend to measure the performance change just copying it all to see if I even need to optimize to just copy the needed 36 bytes. The diffstat for introducing a clear_siginfo to ensure we have made those memsets is huge so I am worried about introducing bugs along the way or missing something. arch/alpha/kernel/osf_sys.c | 1 + arch/alpha/kernel/signal.c | 2 ++ arch/alpha/kernel/traps.c | 5 ++++ arch/alpha/mm/fault.c | 2 ++ arch/arc/kernel/traps.c | 14 ++++++---- arch/arc/mm/fault.c | 1 + arch/arm/kernel/ptrace.c | 2 ++ arch/arm/kernel/swp_emulate.c | 1 + arch/arm/kernel/traps.c | 5 ++++ arch/arm/mm/alignment.c | 1 + arch/arm/mm/fault.c | 3 ++ arch/arm/vfp/vfpmodule.c | 2 +- arch/arm64/kernel/debug-monitors.c | 13 +++++---- arch/arm64/kernel/fpsimd.c | 2 +- arch/arm64/kernel/ptrace.c | 13 +++++---- arch/arm64/kernel/traps.c | 2 ++ arch/arm64/mm/fault.c | 4 +++ arch/blackfin/kernel/traps.c | 1 + arch/c6x/kernel/traps.c | 1 + arch/cris/mm/fault.c | 1 + arch/frv/kernel/traps.c | 7 +++++ arch/frv/mm/fault.c | 1 + arch/hexagon/kernel/traps.c | 1 + arch/hexagon/mm/vm_fault.c | 2 ++ arch/ia64/kernel/brl_emu.c | 3 ++ arch/ia64/kernel/signal.c | 2 ++ arch/ia64/kernel/traps.c | 3 +- arch/ia64/kernel/unaligned.c | 1 + arch/ia64/mm/fault.c | 1 + arch/m32r/kernel/traps.c | 1 + arch/m32r/mm/fault.c | 1 + arch/m68k/kernel/traps.c | 2 ++ arch/m68k/mm/fault.c | 3 +- arch/metag/kernel/traps.c | 2 ++ arch/metag/mm/fault.c | 2 ++ arch/microblaze/kernel/exceptions.c | 1 + arch/microblaze/mm/fault.c | 1 + arch/mips/kernel/traps.c | 29 +++++++++++++------ arch/mips/mm/fault.c | 1 + arch/mn10300/kernel/fpu.c | 1 + arch/mn10300/kernel/traps.c | 1 + arch/mn10300/mm/fault.c | 1 + arch/mn10300/mm/misalignment.c | 2 ++ arch/nios2/kernel/traps.c | 1 + arch/openrisc/kernel/traps.c | 5 +++- arch/openrisc/mm/fault.c | 1 + arch/parisc/kernel/ptrace.c | 1 + arch/parisc/kernel/traps.c | 2 ++ arch/parisc/kernel/unaligned.c | 2 ++ arch/parisc/math-emu/driver.c | 1 + arch/parisc/mm/fault.c | 1 + arch/powerpc/kernel/process.c | 2 ++ arch/powerpc/kernel/traps.c | 4 +-- arch/powerpc/mm/fault.c | 1 + arch/powerpc/platforms/cell/spufs/fault.c | 2 +- arch/s390/kernel/traps.c | 3 ++ arch/s390/mm/fault.c | 2 ++ arch/score/kernel/traps.c | 1 + arch/score/mm/fault.c | 1 + arch/sh/kernel/hw_breakpoint.c | 1 + arch/sh/kernel/traps_32.c | 4 +++ arch/sh/math-emu/math.c | 1 + arch/sh/mm/fault.c | 1 + arch/sparc/kernel/process_64.c | 1 + arch/sparc/kernel/sys_sparc_32.c | 1 + arch/sparc/kernel/sys_sparc_64.c | 1 + arch/sparc/kernel/traps_32.c | 10 +++++++ arch/sparc/kernel/traps_64.c | 15 ++++++++++ arch/sparc/kernel/unaligned_32.c | 1 + arch/sparc/mm/fault_32.c | 1 + arch/sparc/mm/fault_64.c | 1 + arch/tile/kernel/hardwall.c | 1 + arch/tile/kernel/ptrace.c | 2 +- arch/tile/kernel/single_step.c | 24 +++++++++------- arch/tile/kernel/traps.c | 4 ++- arch/tile/kernel/unaligned.c | 46 +++++++++++++++++-------------- arch/tile/mm/fault.c | 1 + arch/um/kernel/ptrace.c | 2 +- arch/um/kernel/trap.c | 4 ++- arch/unicore32/kernel/fpu-ucf64.c | 3 +- arch/unicore32/mm/fault.c | 3 ++ arch/x86/entry/vsyscall/vsyscall_64.c | 2 +- arch/x86/kernel/ptrace.c | 2 +- arch/x86/kernel/traps.c | 3 ++ arch/x86/kvm/mmu.c | 1 + arch/x86/mm/fault.c | 1 + arch/xtensa/kernel/ptrace.c | 1 + arch/xtensa/kernel/traps.c | 1 + arch/xtensa/mm/fault.c | 1 + drivers/usb/core/devio.c | 4 +-- fs/fcntl.c | 1 + include/linux/ptrace.h | 2 +- include/linux/signal.h | 5 ++++ ipc/mqueue.c | 1 + kernel/debug/kdb/kdb_main.c | 1 + kernel/ptrace.c | 2 +- kernel/seccomp.c | 2 +- kernel/signal.c | 21 ++++++++++---- kernel/time/posix-timers.c | 2 +- mm/memory-failure.c | 1 + 100 files changed, 272 insertions(+), 85 deletions(-) Eric ^ permalink raw reply [flat|nested] 24+ messages in thread
[parent not found: <878tjlbqpt.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>]
* Simplfying copy_siginfo_to_user [not found] ` <878tjlbqpt.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> @ 2017-07-22 20:25 ` Eric W. Biederman [not found] ` <8760ek5ics.fsf_-_-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> 0 siblings, 1 reply; 24+ messages in thread From: Eric W. Biederman @ 2017-07-22 20:25 UTC (permalink / raw) To: Linus Torvalds Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Andrei Vagin, Greg KH, Linux Containers, Pavel Emelyanov, Oleg Nesterov, Linux Kernel Mailing List, Al Viro, Andy Lutomirski, Linux API, Cyrill Gorcunov, Michael Kerrisk, Thomas Gleixner, Willy Tarreau, Andrey Vagin ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org (Eric W. Biederman) writes: > Linus Torvalds <torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org> writes: > >> On Tue, Jul 18, 2017 at 7:06 AM, Eric W. Biederman >> <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> wrote: >>> struct siginfo is a union and the kernel since 2.4 has been hiding a union >>> tag in the high 16bits of si_code using the values: >>> __SI_KILL >>> __SI_TIMER >>> __SI_POLL >>> __SI_FAULT >>> __SI_CHLD >>> __SI_RT >>> __SI_MESGQ >>> __SI_SYS >>> >>> While this looks plausible on the surface, in practice this situation has >>> not worked well. >> >> So on the whole I think we just need to do this, but the part I really >> hate about this series is still this the siginfo_layout() part. >> >> I can well believe that it is needed for the compat case. siginfo is a >> piece of crap crazy type, and re-ordering fields for compat is >> something we are always going to have to do. >> >> But for the native case, the *only* reason we do not just copy the >> siginfo as-is seems to be that it's just too big, due to other bad >> design decisions in siginfo ("let's make sure it's big enough by >> allocating 512 bytes for it). >> >> And afaik, absolutely nobody uses more than about 36 bytes of that >> 512-byte _sifields union (and that one use is SIGILL with three >> pointers and three integers and some padding. >> >> So why don't we just say "screw this idiotic layout crap, and just >> unconditionally copy that much smaller maximum of bytes"? >> >> Leave that layout thing purely for compat handling. > > I completely agree. So I just did some measurements to see what the performance impact is of doing the simple and obvious thing of always copying the entire siginfo around. There is a fair amount of variation in my timings but for the whole change I see about a 20ns increase in time taken to send a signal with siginfo from the current process to the current process. AKA timing kill(getpid(),...). I played with some clever changes such as limiting the copy to 48 bytes, disabling the memset and the like but I could not get a strong enough signal to say that any one change removed the extra or a clear part of it 20ns. Do we care about those 20ns for signal deliver? I suspect from my previous numbers that if Andy can get signal delivery to use sysret it will more than make up for the small increase in cost here. Eric ^ permalink raw reply [flat|nested] 24+ messages in thread
[parent not found: <8760ek5ics.fsf_-_-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>]
* Re: Simplfying copy_siginfo_to_user [not found] ` <8760ek5ics.fsf_-_-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> @ 2017-07-24 17:43 ` Linus Torvalds [not found] ` <CA+55aFyH5W2doo9vxXta_-pXfNXqQ19d7z48k1hmfAot+aJvMw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2017-07-25 1:37 ` Al Viro 0 siblings, 2 replies; 24+ messages in thread From: Linus Torvalds @ 2017-07-24 17:43 UTC (permalink / raw) To: Eric W. Biederman Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Andrei Vagin, Greg KH, Linux Containers, Pavel Emelyanov, Oleg Nesterov, Linux Kernel Mailing List, Al Viro, Andy Lutomirski, Linux API, Cyrill Gorcunov, Michael Kerrisk, Thomas Gleixner, Willy Tarreau, Andrey Vagin On Sat, Jul 22, 2017 at 1:25 PM, Eric W. Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> wrote: > I played with some clever changes such as limiting the copy to 48 bytes, > disabling the memset and the like but I could not get a strong enough > signal to say that any one change removed the extra or a clear part of > it 20ns. What CPU did you use? Because the SMAP bit in particular matters. The field-by-field copies are extremely slow on modern CPU's that implement SMAP, unless you also use the special "unsafe_put_user()" code (or the nasty old put_user_ex() code that some of the x86 signal code uses). So one of the advantages of just copy_to_user() ends up being visible only on Broadwell+ (or whatever the SMAP cutoff is). Linus ^ permalink raw reply [flat|nested] 24+ messages in thread
[parent not found: <CA+55aFyH5W2doo9vxXta_-pXfNXqQ19d7z48k1hmfAot+aJvMw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: Simplfying copy_siginfo_to_user [not found] ` <CA+55aFyH5W2doo9vxXta_-pXfNXqQ19d7z48k1hmfAot+aJvMw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2017-07-24 19:01 ` Eric W. Biederman 0 siblings, 0 replies; 24+ messages in thread From: Eric W. Biederman @ 2017-07-24 19:01 UTC (permalink / raw) To: Linus Torvalds Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Andrei Vagin, Greg KH, Linux Containers, Pavel Emelyanov, Oleg Nesterov, Linux Kernel Mailing List, Al Viro, Andy Lutomirski, Linux API, Cyrill Gorcunov, Michael Kerrisk, Thomas Gleixner, Willy Tarreau, Andrey Vagin Linus Torvalds <torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org> writes: > On Sat, Jul 22, 2017 at 1:25 PM, Eric W. Biederman > <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> wrote: >> I played with some clever changes such as limiting the copy to 48 bytes, >> disabling the memset and the like but I could not get a strong enough >> signal to say that any one change removed the extra or a clear part of >> it 20ns. > > What CPU did you use? Because the SMAP bit in particular matters. > > The field-by-field copies are extremely slow on modern CPU's that > implement SMAP, unless you also use the special "unsafe_put_user()" > code (or the nasty old put_user_ex() code that some of the x86 signal > code uses). > > So one of the advantages of just copy_to_user() ends up being visible > only on Broadwell+ (or whatever the SMAP cutoff is). Good point. The cpu I was testing on was an AMD A10. I don't actually have a cpu that supports SMAP handy. If you would like I can post the minimal patches and benckmark so anyone who is interested could reproduce this for themselves. I suspect that if it is down to only 20ns without SMAP this will definitely be a performance improvement in the presence of SMAP. Eric ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Simplfying copy_siginfo_to_user 2017-07-24 17:43 ` Linus Torvalds [not found] ` <CA+55aFyH5W2doo9vxXta_-pXfNXqQ19d7z48k1hmfAot+aJvMw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2017-07-25 1:37 ` Al Viro 2017-07-31 16:37 ` Eric W. Biederman 1 sibling, 1 reply; 24+ messages in thread From: Al Viro @ 2017-07-25 1:37 UTC (permalink / raw) To: Linus Torvalds Cc: Eric W. Biederman, Linux Kernel Mailing List, Andy Lutomirski, Oleg Nesterov, Andrei Vagin, Thomas Gleixner, Greg KH, Andrey Vagin, Serge Hallyn, Pavel Emelyanov, Cyrill Gorcunov, Peter Zijlstra, Willy Tarreau, linux-arch, Linux API, Linux Containers, Michael Kerrisk On Mon, Jul 24, 2017 at 10:43:34AM -0700, Linus Torvalds wrote: > On Sat, Jul 22, 2017 at 1:25 PM, Eric W. Biederman > <ebiederm@xmission.com> wrote: > > I played with some clever changes such as limiting the copy to 48 bytes, > > disabling the memset and the like but I could not get a strong enough > > signal to say that any one change removed the extra or a clear part of > > it 20ns. > > What CPU did you use? Because the SMAP bit in particular matters. > > The field-by-field copies are extremely slow on modern CPU's that > implement SMAP, unless you also use the special "unsafe_put_user()" > code (or the nasty old put_user_ex() code that some of the x86 signal > code uses). > > So one of the advantages of just copy_to_user() ends up being visible > only on Broadwell+ (or whatever the SMAP cutoff is). Guys, could you take a look at vfs.git#work.siginfo? I'd been pretty much buried lately (and probably will for several more weeks - long-distance moves *suck*), so that thing got stalled, but it might be worth a look. The code generated in copy_siginfo_to_user() in it looks reasonably good, we don't copy more than we need and all copying to userland is done by copy_to_user() - one call per call of copy_siginfo_to_user(), so SMAP crap is not an issue. The next thing I hope to do is converting compat side of that thing to the same; that got stalled. Al "Buried in boxes" Viro... ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Simplfying copy_siginfo_to_user 2017-07-25 1:37 ` Al Viro @ 2017-07-31 16:37 ` Eric W. Biederman 0 siblings, 0 replies; 24+ messages in thread From: Eric W. Biederman @ 2017-07-31 16:37 UTC (permalink / raw) To: Al Viro Cc: Linus Torvalds, Linux Kernel Mailing List, Andy Lutomirski, Oleg Nesterov, Andrei Vagin, Thomas Gleixner, Greg KH, Andrey Vagin, Serge Hallyn, Pavel Emelyanov, Cyrill Gorcunov, Peter Zijlstra, Willy Tarreau, linux-arch, Linux API, Linux Containers, Michael Kerrisk Al Viro <viro@ZenIV.linux.org.uk> writes: 2> On Mon, Jul 24, 2017 at 10:43:34AM -0700, Linus Torvalds wrote: >> On Sat, Jul 22, 2017 at 1:25 PM, Eric W. Biederman >> <ebiederm@xmission.com> wrote: >> > I played with some clever changes such as limiting the copy to 48 bytes, >> > disabling the memset and the like but I could not get a strong enough >> > signal to say that any one change removed the extra or a clear part of >> > it 20ns. >> >> What CPU did you use? Because the SMAP bit in particular matters. >> >> The field-by-field copies are extremely slow on modern CPU's that >> implement SMAP, unless you also use the special "unsafe_put_user()" >> code (or the nasty old put_user_ex() code that some of the x86 signal >> code uses). >> >> So one of the advantages of just copy_to_user() ends up being visible >> only on Broadwell+ (or whatever the SMAP cutoff is). > > Guys, could you take a look at vfs.git#work.siginfo? I'd been pretty > much buried lately (and probably will for several more weeks - long-distance > moves *suck*), so that thing got stalled, but it might be worth a > look. There is some good stuff in there. If you don't mind I am going to cherry pick out your unification of struct siginfo and struct compat_siginfo. > The code generated in copy_siginfo_to_user() in it looks reasonably good, > we don't copy more than we need and all copying to userland is done > by copy_to_user() - one call per call of copy_siginfo_to_user(), so > SMAP crap is not an issue. There is actually a core problem with doing things that way. You rely on having the siginfo union member stored in the high bits of si_code. I have just fixed that in my tree and replaced using the high bits with calling the function siginfo_layout. It has been a significant problem storing the union member differently in the kernel than in userspace. It has allowed for some pretty horrendous gaffs in the archictecures changing the meaning of SI_USER when specific signals are delivered over. It has also meant that ptrace siginfo injection and tg_sigqueueinfo have been broken for some signals almost since the interface was added. Without any optimization and just changing the code to be copy_to_user I am seeing a maybe 2% slowdown. Given that no one has seemed to care overly for the performance of signal delivery I suspect an almost unmeasurable slowdown is a reasonable tradeoff for simpler code. > The next thing I hope to do is converting compat side of that thing to > the same; that got stalled. All of that said your precise copying code appears reasonable and quite nice so I may adopt it on the compat side. > Al "Buried in boxes" Viro... Eric "Also Buried in boxes" Biederman ^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2017-08-08 23:19 UTC | newest] Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- [not found] <87lgot2loq.fsf@xmission.com> [not found] ` <87zid90vye.fsf_-_@xmission.com> [not found] ` <20170615225426.GP31671@ZenIV.linux.org.uk> [not found] ` <87poe4zrs1.fsf@xmission.com> [not found] ` <CA+55aFxpv+gchzs7AYgSC8feAOV=B6mjFgBVm4Kx+83J2CNE-w@mail.gmail.com> [not found] ` <87poe3vsa9.fsf@xmission.com> [not found] ` <CALCETrX=SquyR8JZqHDNx=_FQKQo-0u9AxfdUwJs_hujVO2A-g@mail.gmail.com> [not found] ` <87h8zfua59.fsf@xmission.com> [not found] ` <CALCETrWPBn31Dye=81r2ZMainNOnDy5c_QxbU2uRjnJs0ie=Zg@mail.gmail.com> [not found] ` <87r2yjsuwl.fsf@xmission.com> [not found] ` <20170616191602.GA10675@1wt.eu> 2017-06-30 12:36 ` [PATCH 0/8] signal: Fix sending signals with siginfo Eric W. Biederman 2017-07-18 14:04 ` [PATCH v2 0/7] " Eric W. Biederman 2017-07-18 14:06 ` [PATCH 1/7] signal/alpha: Document a conflict with SI_USER for SIGTRAP Eric W. Biederman [not found] ` <20170718140651.15973-1-ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> 2017-07-18 18:22 ` Richard Henderson 2017-07-18 14:06 ` [PATCH 4/7] signal/mips: Document a conflict with SI_USER with SIGFPE Eric W. Biederman 2017-08-07 16:18 ` Maciej W. Rozycki 2017-08-07 17:41 ` Linus Torvalds 2017-08-07 19:55 ` Ralf Baechle 2017-08-08 15:29 ` Eric W. Biederman 2017-08-08 23:19 ` Maciej W. Rozycki [not found] ` <87o9shg7t7.fsf_-_-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> 2017-07-18 14:06 ` [PATCH 2/7] signal/ia64: " Eric W. Biederman 2017-07-18 14:06 ` [PATCH 3/7] signal/sparc: " Eric W. Biederman 2017-07-18 14:06 ` [PATCH 5/7] signal/testing: Don't look for __SI_FAULT in userspace Eric W. Biederman 2017-07-18 14:06 ` [PATCH 6/7] fcntl: Don't use ambiguous SIG_POLL si_codes Eric W. Biederman [not found] ` <20170718140651.15973-6-ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> 2017-07-20 16:16 ` Oleg Nesterov 2017-07-21 2:33 ` Eric W. Biederman 2017-07-18 14:06 ` [PATCH 7/7] signal: Remove kernel interal si_code magic Eric W. Biederman [not found] ` <20170718140651.15973-7-ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> 2017-07-18 16:57 ` Linus Torvalds [not found] ` <CA+55aFyKsmf+BpYjcH30MGpHTDJ=zgYPx6kwyEB9CXXFxj_xsw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2017-07-18 17:27 ` Eric W. Biederman [not found] ` <878tjlbqpt.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> 2017-07-22 20:25 ` Simplfying copy_siginfo_to_user Eric W. Biederman [not found] ` <8760ek5ics.fsf_-_-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> 2017-07-24 17:43 ` Linus Torvalds [not found] ` <CA+55aFyH5W2doo9vxXta_-pXfNXqQ19d7z48k1hmfAot+aJvMw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2017-07-24 19:01 ` Eric W. Biederman 2017-07-25 1:37 ` Al Viro 2017-07-31 16:37 ` Eric W. Biederman
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).