Commit 64a76d0d authored by Eric W. Biederman's avatar Eric W. Biederman

signal: Fix sending signals with siginfo

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.

v3:
   - Corrected the patches so they bisect properly
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
Signed-off-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
parents 4d28df61 cc731525
......@@ -6,4 +6,18 @@
#include <asm-generic/siginfo.h>
/*
* SIGFPE si_codes
*/
#ifdef __KERNEL__
#define FPE_FIXME 0 /* Broken dup of SI_USER */
#endif /* __KERNEL__ */
/*
* SIGTRAP si_codes
*/
#ifdef __KERNEL__
#define TRAP_FIXME 0 /* Broken dup of SI_USER */
#endif /* __KERNEL__ */
#endif
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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 */
......@@ -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
......
......@@ -98,27 +98,30 @@ 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
/*
* SIGFPE si_codes
*/
#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 */
#ifdef __KERNEL__
#define FPE_FIXME 0 /* Broken dup of SI_USER */
#endif /* __KERNEL__ */
#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
......
......@@ -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;
......
......@@ -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;
......
......@@ -120,7 +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 0 /* Broken dup of SI_USER */
#endif /* __KERNEL__ */
#endif /* _UAPI_ASM_SIGINFO_H */
......@@ -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);
......
......@@ -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);
}
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -16,10 +16,17 @@
#define SI_NOINFO 32767 /* no information in siginfo_t */
/*
* SIGFPE si_codes
*/
#ifdef __KERNEL__
#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 */
......@@ -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);
......
......@@ -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;
......
......@@ -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;
......
......@@ -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
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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 - POLL_IN) >= NSIGPOLL));
if (reason - POLL_IN >= NSIGPOLL)
si.si_band = ~0L;
else
......
......@@ -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().
......
......@@ -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.
*/
......@@ -380,10 +394,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) && \
......
......@@ -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,8 +158,8 @@ 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 -5 /* sent by queued SIGIO */
#define SI_TKILL -6 /* sent by tkill system call */
......@@ -194,85 +171,85 @@ 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 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 */
#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 SYS_SECCOMP 1 /* seccomp triggered */
#define NSIGSYS 1
/*
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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";
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment