aboutsummaryrefslogtreecommitdiffstats
path: root/features/seccomp/signal-x86-add-SIGSYS-info-and-make-it-synchronous.patch
diff options
context:
space:
mode:
Diffstat (limited to 'features/seccomp/signal-x86-add-SIGSYS-info-and-make-it-synchronous.patch')
-rw-r--r--features/seccomp/signal-x86-add-SIGSYS-info-and-make-it-synchronous.patch174
1 files changed, 174 insertions, 0 deletions
diff --git a/features/seccomp/signal-x86-add-SIGSYS-info-and-make-it-synchronous.patch b/features/seccomp/signal-x86-add-SIGSYS-info-and-make-it-synchronous.patch
new file mode 100644
index 00000000..735a9b94
--- /dev/null
+++ b/features/seccomp/signal-x86-add-SIGSYS-info-and-make-it-synchronous.patch
@@ -0,0 +1,174 @@
+From 5b84a784a5f5186e35aea6efad849d8898f527a2 Mon Sep 17 00:00:00 2001
+From: Will Drewry <wad@chromium.org>
+Date: Thu, 12 Apr 2012 16:48:00 -0500
+Subject: [PATCH] signal, x86: add SIGSYS info and make it synchronous.
+
+commit a0727e8ce513fe6890416da960181ceb10fbfae6 upstream.
+
+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 88ebdda6159ffc15699f204c33feb3e431bf9bdc
+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>
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+---
+ arch/x86/ia32/ia32_signal.c | 4 ++++
+ arch/x86/include/asm/ia32.h | 6 ++++++
+ include/asm-generic/siginfo.h | 22 ++++++++++++++++++++++
+ kernel/signal.c | 9 ++++++++-
+ 4 files changed, 40 insertions(+), 1 deletions(-)
+
+diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
+index a69245b..0b3f235 100644
+--- a/arch/x86/ia32/ia32_signal.c
++++ b/arch/x86/ia32/ia32_signal.c
+@@ -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);
+diff --git a/arch/x86/include/asm/ia32.h b/arch/x86/include/asm/ia32.h
+index ee52760..b04cbdb 100644
+--- a/arch/x86/include/asm/ia32.h
++++ b/arch/x86/include/asm/ia32.h
+@@ -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;
+
+diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h
+index 5e5e386..d2c7f29 100644
+--- a/include/asm-generic/siginfo.h
++++ b/include/asm-generic/siginfo.h
+@@ -98,9 +98,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;
+ } __ARCH_SI_ATTRIBUTES siginfo_t;
+
++/* If the arch shares siginfo, then it has SIGSYS. */
++#define __ARCH_SIGSYS
+ #endif
+
+ /*
+@@ -124,6 +133,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
+@@ -134,6 +148,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
+@@ -143,6 +158,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
+
+@@ -240,6 +256,12 @@ typedef struct siginfo {
+ #define NSIGPOLL 6
+
+ /*
++ * SIGSYS si_codes
++ */
++#define SYS_SECCOMP (__SI_SYS|1) /* seccomp triggered */
++#define NSIGSYS 1
++
++/*
+ * sigevent definitions
+ *
+ * It seems likely that SIGEV_THREAD will have to be handled from
+diff --git a/kernel/signal.c b/kernel/signal.c
+index 17afcaf..1a006b5 100644
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -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);
+--
+1.7.9.1
+