diff options
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.patch | 174 |
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 + |