signal, x86: add SIGSYS info and make it synchronous.
This change enables SIGSYS, defines _sigfields._sigsys, and adds
x86 (compat) arch support. _sigsys defines fields which allow
a signal handler to receive the triggering system call number,
the relevant AUDIT_ARCH_* value for that number, and the address
of the callsite.
SIGSYS is added to the SYNCHRONOUS_MASK because it is desirable for it
to have setup_frame() called for it. The goal is to ensure that
ucontext_t reflects the machine state from the time-of-syscall and not
from another signal handler.
The first consumer of SIGSYS would be seccomp filter. In particular,
a filter program could specify a new return value, SECCOMP_RET_TRAP,
which would result in the system call being denied and the calling
thread signaled. This also means that implementing arch-specific
support can be dependent upon HAVE_ARCH_SECCOMP_FILTER.
Suggested-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Will Drewry <wad@chromium.org>
Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
Reviewed-by: H. Peter Anvin <hpa@zytor.com>
Acked-by: Eric Paris <eparis@redhat.com>
v18: - added acked by, rebase
v17: - rebase and reviewed-by addition
v14: - rebase/nochanges
v13: - rebase on to 88ebdda615
v12: - reworded changelog (oleg@redhat.com)
v11: - fix dropped words in the change description
- added fallback copy_siginfo support.
- added __ARCH_SIGSYS define to allow stepped arch support.
v10: - first version based on suggestion
Signed-off-by: James Morris <james.l.morris@oracle.com>
This commit is contained in:
parent
acf3b2c71e
commit
a0727e8ce5
@ -67,6 +67,10 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
|
||||
switch (from->si_code >> 16) {
|
||||
case __SI_FAULT >> 16:
|
||||
break;
|
||||
case __SI_SYS >> 16:
|
||||
put_user_ex(from->si_syscall, &to->si_syscall);
|
||||
put_user_ex(from->si_arch, &to->si_arch);
|
||||
break;
|
||||
case __SI_CHLD >> 16:
|
||||
if (ia32) {
|
||||
put_user_ex(from->si_utime, &to->si_utime);
|
||||
|
@ -144,6 +144,12 @@ typedef struct compat_siginfo {
|
||||
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
int _fd;
|
||||
} _sigpoll;
|
||||
|
||||
struct {
|
||||
unsigned int _call_addr; /* calling insn */
|
||||
int _syscall; /* triggering system call number */
|
||||
unsigned int _arch; /* AUDIT_ARCH_* of syscall */
|
||||
} _sigsys;
|
||||
} _sifields;
|
||||
} compat_siginfo_t;
|
||||
|
||||
|
@ -90,9 +90,18 @@ typedef struct siginfo {
|
||||
__ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
int _fd;
|
||||
} _sigpoll;
|
||||
|
||||
/* SIGSYS */
|
||||
struct {
|
||||
void __user *_call_addr; /* calling insn */
|
||||
int _syscall; /* triggering system call number */
|
||||
unsigned int _arch; /* AUDIT_ARCH_* of syscall */
|
||||
} _sigsys;
|
||||
} _sifields;
|
||||
} siginfo_t;
|
||||
|
||||
/* If the arch shares siginfo, then it has SIGSYS. */
|
||||
#define __ARCH_SIGSYS
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -116,6 +125,11 @@ typedef struct siginfo {
|
||||
#define si_addr_lsb _sifields._sigfault._addr_lsb
|
||||
#define si_band _sifields._sigpoll._band
|
||||
#define si_fd _sifields._sigpoll._fd
|
||||
#ifdef __ARCH_SIGSYS
|
||||
#define si_call_addr _sifields._sigsys._call_addr
|
||||
#define si_syscall _sifields._sigsys._syscall
|
||||
#define si_arch _sifields._sigsys._arch
|
||||
#endif
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define __SI_MASK 0xffff0000u
|
||||
@ -126,6 +140,7 @@ typedef struct siginfo {
|
||||
#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
|
||||
#define __SI_KILL 0
|
||||
@ -135,6 +150,7 @@ typedef struct siginfo {
|
||||
#define __SI_CHLD 0
|
||||
#define __SI_RT 0
|
||||
#define __SI_MESGQ 0
|
||||
#define __SI_SYS 0
|
||||
#define __SI_CODE(T,N) (N)
|
||||
#endif
|
||||
|
||||
@ -231,6 +247,12 @@ typedef struct siginfo {
|
||||
#define POLL_HUP (__SI_POLL|6) /* device disconnected */
|
||||
#define NSIGPOLL 6
|
||||
|
||||
/*
|
||||
* SIGSYS si_codes
|
||||
*/
|
||||
#define SYS_SECCOMP (__SI_SYS|1) /* seccomp triggered */
|
||||
#define NSIGSYS 1
|
||||
|
||||
/*
|
||||
* sigevent definitions
|
||||
*
|
||||
|
@ -160,7 +160,7 @@ void recalc_sigpending(void)
|
||||
|
||||
#define SYNCHRONOUS_MASK \
|
||||
(sigmask(SIGSEGV) | sigmask(SIGBUS) | sigmask(SIGILL) | \
|
||||
sigmask(SIGTRAP) | sigmask(SIGFPE))
|
||||
sigmask(SIGTRAP) | sigmask(SIGFPE) | sigmask(SIGSYS))
|
||||
|
||||
int next_signal(struct sigpending *pending, sigset_t *mask)
|
||||
{
|
||||
@ -2706,6 +2706,13 @@ int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from)
|
||||
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:
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user