Commit a0727e8c authored by Will Drewry's avatar Will Drewry Committed by James Morris

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: default avatarH. Peter Anvin <hpa@zytor.com>
Signed-off-by: default avatarWill Drewry <wad@chromium.org>
Acked-by: default avatarSerge Hallyn <serge.hallyn@canonical.com>
Reviewed-by: default avatarH. Peter Anvin <hpa@zytor.com>
Acked-by: default avatarEric Paris <eparis@redhat.com>

v18: - added acked by, rebase
v17: - rebase and reviewed-by addition
v14: - rebase/nochanges
v13: - rebase on to 88ebdda6
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: default avatarJames Morris <james.l.morris@oracle.com>
parent acf3b2c7
...@@ -67,6 +67,10 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) ...@@ -67,6 +67,10 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
switch (from->si_code >> 16) { switch (from->si_code >> 16) {
case __SI_FAULT >> 16: case __SI_FAULT >> 16:
break; 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: case __SI_CHLD >> 16:
if (ia32) { if (ia32) {
put_user_ex(from->si_utime, &to->si_utime); put_user_ex(from->si_utime, &to->si_utime);
......
...@@ -144,6 +144,12 @@ typedef struct compat_siginfo { ...@@ -144,6 +144,12 @@ typedef struct compat_siginfo {
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd; int _fd;
} _sigpoll; } _sigpoll;
struct {
unsigned int _call_addr; /* calling insn */
int _syscall; /* triggering system call number */
unsigned int _arch; /* AUDIT_ARCH_* of syscall */
} _sigsys;
} _sifields; } _sifields;
} compat_siginfo_t; } compat_siginfo_t;
......
...@@ -90,9 +90,18 @@ typedef struct siginfo { ...@@ -90,9 +90,18 @@ typedef struct siginfo {
__ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */ __ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd; int _fd;
} _sigpoll; } _sigpoll;
/* SIGSYS */
struct {
void __user *_call_addr; /* calling insn */
int _syscall; /* triggering system call number */
unsigned int _arch; /* AUDIT_ARCH_* of syscall */
} _sigsys;
} _sifields; } _sifields;
} siginfo_t; } siginfo_t;
/* If the arch shares siginfo, then it has SIGSYS. */
#define __ARCH_SIGSYS
#endif #endif
/* /*
...@@ -116,6 +125,11 @@ typedef struct siginfo { ...@@ -116,6 +125,11 @@ typedef struct siginfo {
#define si_addr_lsb _sifields._sigfault._addr_lsb #define si_addr_lsb _sifields._sigfault._addr_lsb
#define si_band _sifields._sigpoll._band #define si_band _sifields._sigpoll._band
#define si_fd _sifields._sigpoll._fd #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__ #ifdef __KERNEL__
#define __SI_MASK 0xffff0000u #define __SI_MASK 0xffff0000u
...@@ -126,6 +140,7 @@ typedef struct siginfo { ...@@ -126,6 +140,7 @@ typedef struct siginfo {
#define __SI_CHLD (4 << 16) #define __SI_CHLD (4 << 16)
#define __SI_RT (5 << 16) #define __SI_RT (5 << 16)
#define __SI_MESGQ (6 << 16) #define __SI_MESGQ (6 << 16)
#define __SI_SYS (7 << 16)
#define __SI_CODE(T,N) ((T) | ((N) & 0xffff)) #define __SI_CODE(T,N) ((T) | ((N) & 0xffff))
#else #else
#define __SI_KILL 0 #define __SI_KILL 0
...@@ -135,6 +150,7 @@ typedef struct siginfo { ...@@ -135,6 +150,7 @@ typedef struct siginfo {
#define __SI_CHLD 0 #define __SI_CHLD 0
#define __SI_RT 0 #define __SI_RT 0
#define __SI_MESGQ 0 #define __SI_MESGQ 0
#define __SI_SYS 0
#define __SI_CODE(T,N) (N) #define __SI_CODE(T,N) (N)
#endif #endif
...@@ -231,6 +247,12 @@ typedef struct siginfo { ...@@ -231,6 +247,12 @@ typedef struct siginfo {
#define POLL_HUP (__SI_POLL|6) /* device disconnected */ #define POLL_HUP (__SI_POLL|6) /* device disconnected */
#define NSIGPOLL 6 #define NSIGPOLL 6
/*
* SIGSYS si_codes
*/
#define SYS_SECCOMP (__SI_SYS|1) /* seccomp triggered */
#define NSIGSYS 1
/* /*
* sigevent definitions * sigevent definitions
* *
......
...@@ -160,7 +160,7 @@ void recalc_sigpending(void) ...@@ -160,7 +160,7 @@ void recalc_sigpending(void)
#define SYNCHRONOUS_MASK \ #define SYNCHRONOUS_MASK \
(sigmask(SIGSEGV) | sigmask(SIGBUS) | sigmask(SIGILL) | \ (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) 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) ...@@ -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_uid, &to->si_uid);
err |= __put_user(from->si_ptr, &to->si_ptr); err |= __put_user(from->si_ptr, &to->si_ptr);
break; 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 ... */ default: /* this is just in case for now ... */
err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_pid, &to->si_pid);
err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_uid, &to->si_uid);
......
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