aboutsummaryrefslogtreecommitdiffstats
path: root/features/seccomp/seccomp-Add-SECCOMP_RET_TRAP.patch
diff options
context:
space:
mode:
Diffstat (limited to 'features/seccomp/seccomp-Add-SECCOMP_RET_TRAP.patch')
-rw-r--r--features/seccomp/seccomp-Add-SECCOMP_RET_TRAP.patch138
1 files changed, 138 insertions, 0 deletions
diff --git a/features/seccomp/seccomp-Add-SECCOMP_RET_TRAP.patch b/features/seccomp/seccomp-Add-SECCOMP_RET_TRAP.patch
new file mode 100644
index 00000000..31466638
--- /dev/null
+++ b/features/seccomp/seccomp-Add-SECCOMP_RET_TRAP.patch
@@ -0,0 +1,138 @@
+From 365829a1caa9148a289fe895280a1d2ed0e56e37 Mon Sep 17 00:00:00 2001
+From: Will Drewry <wad@chromium.org>
+Date: Thu, 12 Apr 2012 16:48:01 -0500
+Subject: [PATCH] seccomp: Add SECCOMP_RET_TRAP
+
+commit bb6ea4301a1109afdacaee576fedbfcd7152fc86 upstream.
+
+Adds a new return value to seccomp filters that triggers a SIGSYS to be
+delivered with the new SYS_SECCOMP si_code.
+
+This allows in-process system call emulation, including just specifying
+an errno or cleanly dumping core, rather than just dying.
+
+Suggested-by: Markus Gutschke <markus@chromium.org>
+Suggested-by: Julien Tinnes <jln@chromium.org>
+Signed-off-by: Will Drewry <wad@chromium.org>
+Acked-by: Eric Paris <eparis@redhat.com>
+
+v18: - acked-by, rebase
+ - don't mention secure_computing_int() anymore
+v15: - use audit_seccomp/skip
+ - pad out error spacing; clean up switch (indan@nul.nu)
+v14: - n/a
+v13: - rebase on to 88ebdda6159ffc15699f204c33feb3e431bf9bdc
+v12: - rebase on to linux-next
+v11: - clarify the comment (indan@nul.nu)
+ - s/sigtrap/sigsys
+v10: - use SIGSYS, syscall_get_arch, updates arch/Kconfig
+ note suggested-by (though original suggestion had other behaviors)
+v9: - changes to SIGILL
+v8: - clean up based on changes to dependent patches
+v7: - introduction
+Signed-off-by: James Morris <james.l.morris@oracle.com>
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+---
+ arch/Kconfig | 14 +++++++++-----
+ include/asm-generic/siginfo.h | 2 +-
+ include/linux/seccomp.h | 1 +
+ kernel/seccomp.c | 26 ++++++++++++++++++++++++++
+ 4 files changed, 37 insertions(+), 6 deletions(-)
+
+diff --git a/arch/Kconfig b/arch/Kconfig
+index beaab68..66aef13 100644
+--- a/arch/Kconfig
++++ b/arch/Kconfig
+@@ -219,11 +219,15 @@ config ARCH_WANT_OLD_COMPAT_IPC
+ config HAVE_ARCH_SECCOMP_FILTER
+ bool
+ help
+- This symbol should be selected by an architecure if it provides
+- asm/syscall.h, specifically syscall_get_arguments(),
+- syscall_get_arch(), and syscall_set_return_value(). Additionally,
+- its system call entry path must respect a return value of -1 from
+- __secure_computing() and/or secure_computing().
++ This symbol should be selected by an architecure if it provides:
++ asm/syscall.h:
++ - syscall_get_arch()
++ - syscall_get_arguments()
++ - syscall_rollback()
++ - syscall_set_return_value()
++ SIGSYS siginfo_t support must be implemented.
++ __secure_computing()/secure_computing()'s return value must be
++ checked, with -1 resulting in the syscall being skipped.
+
+ config SECCOMP_FILTER
+ def_bool y
+diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h
+index d2c7f29..8ed6777 100644
+--- a/include/asm-generic/siginfo.h
++++ b/include/asm-generic/siginfo.h
+@@ -101,7 +101,7 @@ typedef struct siginfo {
+
+ /* SIGSYS */
+ struct {
+- void __user *_call_addr; /* calling insn */
++ void __user *_call_addr; /* calling user insn */
+ int _syscall; /* triggering system call number */
+ unsigned int _arch; /* AUDIT_ARCH_* of syscall */
+ } _sigsys;
+diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
+index b4ce2c8..317ccb7 100644
+--- a/include/linux/seccomp.h
++++ b/include/linux/seccomp.h
+@@ -19,6 +19,7 @@
+ * selects the least permissive choice.
+ */
+ #define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
++#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
+ #define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
+ #define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
+
+diff --git a/kernel/seccomp.c b/kernel/seccomp.c
+index 5f78fb6..9c38306 100644
+--- a/kernel/seccomp.c
++++ b/kernel/seccomp.c
+@@ -332,6 +332,26 @@ void put_seccomp_filter(struct task_struct *tsk)
+ kfree(freeme);
+ }
+ }
++
++/**
++ * seccomp_send_sigsys - signals the task to allow in-process syscall emulation
++ * @syscall: syscall number to send to userland
++ * @reason: filter-supplied reason code to send to userland (via si_errno)
++ *
++ * Forces a SIGSYS with a code of SYS_SECCOMP and related sigsys info.
++ */
++static void seccomp_send_sigsys(int syscall, int reason)
++{
++ struct siginfo info;
++ memset(&info, 0, sizeof(info));
++ info.si_signo = SIGSYS;
++ info.si_code = SYS_SECCOMP;
++ info.si_call_addr = (void __user *)KSTK_EIP(current);
++ info.si_errno = reason;
++ info.si_arch = syscall_get_arch(current, task_pt_regs(current));
++ info.si_syscall = syscall;
++ force_sig_info(SIGSYS, &info, current);
++}
+ #endif /* CONFIG_SECCOMP_FILTER */
+
+ /*
+@@ -382,6 +402,12 @@ int __secure_computing(int this_syscall)
+ syscall_set_return_value(current, task_pt_regs(current),
+ -data, 0);
+ goto skip;
++ case SECCOMP_RET_TRAP:
++ /* Show the handler the original registers. */
++ syscall_rollback(current, task_pt_regs(current));
++ /* Let the filter pass back 16 bits of data. */
++ seccomp_send_sigsys(this_syscall, data);
++ goto skip;
+ case SECCOMP_RET_ALLOW:
+ return 0;
+ case SECCOMP_RET_KILL:
+--
+1.7.9.1
+