summaryrefslogtreecommitdiffstats
path: root/queue-3.16
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2018-09-16 16:51:10 +0100
committerBen Hutchings <ben@decadent.org.uk>2018-09-16 16:51:10 +0100
commiteda6678bf03971d7a46e6937cdfecdbbf10e83c8 (patch)
treef8956a876700887521e53cddb587ea82b248ce8d /queue-3.16
parent58b9e960c0380f6ccb913c02968bbaed905bce82 (diff)
downloadlinux-stable-queue-eda6678bf03971d7a46e6937cdfecdbbf10e83c8.tar.gz
Add seccomp() syscall for x86, in preparation for SSB mitigation
Diffstat (limited to 'queue-3.16')
-rw-r--r--queue-3.16/seccomp-add-seccomp-syscall.patch220
-rw-r--r--queue-3.16/seccomp-create-internal-mode-setting-function.patch54
-rw-r--r--queue-3.16/seccomp-extract-check-assign-mode-helpers.patch63
-rw-r--r--queue-3.16/seccomp-split-mode-setting-routines.patch122
-rw-r--r--queue-3.16/series4
5 files changed, 463 insertions, 0 deletions
diff --git a/queue-3.16/seccomp-add-seccomp-syscall.patch b/queue-3.16/seccomp-add-seccomp-syscall.patch
new file mode 100644
index 00000000..819f9834
--- /dev/null
+++ b/queue-3.16/seccomp-add-seccomp-syscall.patch
@@ -0,0 +1,220 @@
+From: Kees Cook <keescook@chromium.org>
+Date: Wed, 25 Jun 2014 16:08:24 -0700
+Subject: seccomp: add "seccomp" syscall
+
+commit 48dc92b9fc3926844257316e75ba11eb5c742b2c upstream.
+
+This adds the new "seccomp" syscall with both an "operation" and "flags"
+parameter for future expansion. The third argument is a pointer value,
+used with the SECCOMP_SET_MODE_FILTER operation. Currently, flags must
+be 0. This is functionally equivalent to prctl(PR_SET_SECCOMP, ...).
+
+In addition to the TSYNC flag later in this patch series, there is a
+non-zero chance that this syscall could be used for configuring a fixed
+argument area for seccomp-tracer-aware processes to pass syscall arguments
+in the future. Hence, the use of "seccomp" not simply "seccomp_add_filter"
+for this syscall. Additionally, this syscall uses operation, flags,
+and user pointer for arguments because strictly passing arguments via
+a user pointer would mean seccomp itself would be unable to trivially
+filter the seccomp syscall itself.
+
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Reviewed-by: Oleg Nesterov <oleg@redhat.com>
+Reviewed-by: Andy Lutomirski <luto@amacapital.net>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ arch/Kconfig | 1 +
+ arch/x86/syscalls/syscall_32.tbl | 1 +
+ arch/x86/syscalls/syscall_64.tbl | 1 +
+ include/linux/syscalls.h | 2 ++
+ include/uapi/asm-generic/unistd.h | 4 ++-
+ include/uapi/linux/seccomp.h | 4 +++
+ kernel/seccomp.c | 55 ++++++++++++++++++++++++++++---
+ kernel/sys_ni.c | 3 ++
+ 8 files changed, 65 insertions(+), 6 deletions(-)
+
+--- a/arch/Kconfig
++++ b/arch/Kconfig
+@@ -321,6 +321,7 @@ config HAVE_ARCH_SECCOMP_FILTER
+ - secure_computing is called from a ptrace_event()-safe context
+ - secure_computing return value is checked and a return value of -1
+ results in the system call being skipped immediately.
++ - seccomp syscall wired up
+
+ config SECCOMP_FILTER
+ def_bool y
+--- a/arch/x86/syscalls/syscall_32.tbl
++++ b/arch/x86/syscalls/syscall_32.tbl
+@@ -360,3 +360,4 @@
+ 351 i386 sched_setattr sys_sched_setattr
+ 352 i386 sched_getattr sys_sched_getattr
+ 353 i386 renameat2 sys_renameat2
++354 i386 seccomp sys_seccomp
+--- a/arch/x86/syscalls/syscall_64.tbl
++++ b/arch/x86/syscalls/syscall_64.tbl
+@@ -323,6 +323,7 @@
+ 314 common sched_setattr sys_sched_setattr
+ 315 common sched_getattr sys_sched_getattr
+ 316 common renameat2 sys_renameat2
++317 common seccomp sys_seccomp
+
+ #
+ # x32-specific system call numbers start at 512 to avoid cache impact
+--- a/include/linux/syscalls.h
++++ b/include/linux/syscalls.h
+@@ -866,4 +866,6 @@ asmlinkage long sys_process_vm_writev(pi
+ asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
+ unsigned long idx1, unsigned long idx2);
+ asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags);
++asmlinkage long sys_seccomp(unsigned int op, unsigned int flags,
++ const char __user *uargs);
+ #endif
+--- a/include/uapi/asm-generic/unistd.h
++++ b/include/uapi/asm-generic/unistd.h
+@@ -699,9 +699,11 @@ __SYSCALL(__NR_sched_setattr, sys_sched_
+ __SYSCALL(__NR_sched_getattr, sys_sched_getattr)
+ #define __NR_renameat2 276
+ __SYSCALL(__NR_renameat2, sys_renameat2)
++#define __NR_seccomp 277
++__SYSCALL(__NR_seccomp, sys_seccomp)
+
+ #undef __NR_syscalls
+-#define __NR_syscalls 277
++#define __NR_syscalls 278
+
+ /*
+ * All syscalls below here should go away really,
+--- a/include/uapi/linux/seccomp.h
++++ b/include/uapi/linux/seccomp.h
+@@ -10,6 +10,10 @@
+ #define SECCOMP_MODE_STRICT 1 /* uses hard-coded filter. */
+ #define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */
+
++/* Valid operations for seccomp syscall. */
++#define SECCOMP_SET_MODE_STRICT 0
++#define SECCOMP_SET_MODE_FILTER 1
++
+ /*
+ * All BPF programs must return a 32-bit value.
+ * The bottom 16-bits are for optional return data.
+--- a/kernel/seccomp.c
++++ b/kernel/seccomp.c
+@@ -18,6 +18,7 @@
+ #include <linux/compat.h>
+ #include <linux/sched.h>
+ #include <linux/seccomp.h>
++#include <linux/syscalls.h>
+
+ /* #define SECCOMP_DEBUG 1 */
+
+@@ -314,7 +315,7 @@ free_prog:
+ *
+ * Returns 0 on success and non-zero otherwise.
+ */
+-static long seccomp_attach_user_filter(char __user *user_filter)
++static long seccomp_attach_user_filter(const char __user *user_filter)
+ {
+ struct sock_fprog fprog;
+ long ret = -EFAULT;
+@@ -517,6 +518,7 @@ out:
+ #ifdef CONFIG_SECCOMP_FILTER
+ /**
+ * seccomp_set_mode_filter: internal function for setting seccomp filter
++ * @flags: flags to change filter behavior
+ * @filter: struct sock_fprog containing filter
+ *
+ * This function may be called repeatedly to install additional filters.
+@@ -527,11 +529,16 @@ out:
+ *
+ * Returns 0 on success or -EINVAL on failure.
+ */
+-static long seccomp_set_mode_filter(char __user *filter)
++static long seccomp_set_mode_filter(unsigned int flags,
++ const char __user *filter)
+ {
+ const unsigned long seccomp_mode = SECCOMP_MODE_FILTER;
+ long ret = -EINVAL;
+
++ /* Validate flags. */
++ if (flags != 0)
++ goto out;
++
+ if (!seccomp_may_assign_mode(seccomp_mode))
+ goto out;
+
+@@ -544,12 +551,35 @@ out:
+ return ret;
+ }
+ #else
+-static inline long seccomp_set_mode_filter(char __user *filter)
++static inline long seccomp_set_mode_filter(unsigned int flags,
++ const char __user *filter)
+ {
+ return -EINVAL;
+ }
+ #endif
+
++/* Common entry point for both prctl and syscall. */
++static long do_seccomp(unsigned int op, unsigned int flags,
++ const char __user *uargs)
++{
++ switch (op) {
++ case SECCOMP_SET_MODE_STRICT:
++ if (flags != 0 || uargs != NULL)
++ return -EINVAL;
++ return seccomp_set_mode_strict();
++ case SECCOMP_SET_MODE_FILTER:
++ return seccomp_set_mode_filter(flags, uargs);
++ default:
++ return -EINVAL;
++ }
++}
++
++SYSCALL_DEFINE3(seccomp, unsigned int, op, unsigned int, flags,
++ const char __user *, uargs)
++{
++ return do_seccomp(op, flags, uargs);
++}
++
+ /**
+ * prctl_set_seccomp: configures current->seccomp.mode
+ * @seccomp_mode: requested mode to use
+@@ -559,12 +589,27 @@ static inline long seccomp_set_mode_filt
+ */
+ long prctl_set_seccomp(unsigned long seccomp_mode, char __user *filter)
+ {
++ unsigned int op;
++ char __user *uargs;
++
+ switch (seccomp_mode) {
+ case SECCOMP_MODE_STRICT:
+- return seccomp_set_mode_strict();
++ op = SECCOMP_SET_MODE_STRICT;
++ /*
++ * Setting strict mode through prctl always ignored filter,
++ * so make sure it is always NULL here to pass the internal
++ * check in do_seccomp().
++ */
++ uargs = NULL;
++ break;
+ case SECCOMP_MODE_FILTER:
+- return seccomp_set_mode_filter(filter);
++ op = SECCOMP_SET_MODE_FILTER;
++ uargs = filter;
++ break;
+ default:
+ return -EINVAL;
+ }
++
++ /* prctl interface doesn't have flags, so they are always zero. */
++ return do_seccomp(op, 0, uargs);
+ }
+--- a/kernel/sys_ni.c
++++ b/kernel/sys_ni.c
+@@ -213,3 +213,6 @@ cond_syscall(compat_sys_open_by_handle_a
+
+ /* compare kernel pointers */
+ cond_syscall(sys_kcmp);
++
++/* operate on Secure Computing state */
++cond_syscall(sys_seccomp);
diff --git a/queue-3.16/seccomp-create-internal-mode-setting-function.patch b/queue-3.16/seccomp-create-internal-mode-setting-function.patch
new file mode 100644
index 00000000..cb5e9424
--- /dev/null
+++ b/queue-3.16/seccomp-create-internal-mode-setting-function.patch
@@ -0,0 +1,54 @@
+From: Kees Cook <keescook@chromium.org>
+Date: Wed, 21 May 2014 15:02:11 -0700
+Subject: seccomp: create internal mode-setting function
+
+commit d78ab02c2c194257a03355fbb79eb721b381d105 upstream.
+
+In preparation for having other callers of the seccomp mode setting
+logic, split the prctl entry point away from the core logic that performs
+seccomp mode setting.
+
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Reviewed-by: Oleg Nesterov <oleg@redhat.com>
+Reviewed-by: Andy Lutomirski <luto@amacapital.net>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ kernel/seccomp.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+--- a/kernel/seccomp.c
++++ b/kernel/seccomp.c
+@@ -473,7 +473,7 @@ long prctl_get_seccomp(void)
+ }
+
+ /**
+- * prctl_set_seccomp: configures current->seccomp.mode
++ * seccomp_set_mode: internal function for setting seccomp mode
+ * @seccomp_mode: requested mode to use
+ * @filter: optional struct sock_fprog for use with SECCOMP_MODE_FILTER
+ *
+@@ -486,7 +486,7 @@ long prctl_get_seccomp(void)
+ *
+ * Returns 0 on success or -EINVAL on failure.
+ */
+-long prctl_set_seccomp(unsigned long seccomp_mode, char __user *filter)
++static long seccomp_set_mode(unsigned long seccomp_mode, char __user *filter)
+ {
+ long ret = -EINVAL;
+
+@@ -517,3 +517,15 @@ long prctl_set_seccomp(unsigned long sec
+ out:
+ return ret;
+ }
++
++/**
++ * prctl_set_seccomp: configures current->seccomp.mode
++ * @seccomp_mode: requested mode to use
++ * @filter: optional struct sock_fprog for use with SECCOMP_MODE_FILTER
++ *
++ * Returns 0 on success or -EINVAL on failure.
++ */
++long prctl_set_seccomp(unsigned long seccomp_mode, char __user *filter)
++{
++ return seccomp_set_mode(seccomp_mode, filter);
++}
diff --git a/queue-3.16/seccomp-extract-check-assign-mode-helpers.patch b/queue-3.16/seccomp-extract-check-assign-mode-helpers.patch
new file mode 100644
index 00000000..73137995
--- /dev/null
+++ b/queue-3.16/seccomp-extract-check-assign-mode-helpers.patch
@@ -0,0 +1,63 @@
+From: Kees Cook <keescook@chromium.org>
+Date: Wed, 25 Jun 2014 15:38:02 -0700
+Subject: seccomp: extract check/assign mode helpers
+
+commit 1f41b450416e689b9b7c8bfb750a98604f687a9b upstream.
+
+To support splitting mode 1 from mode 2, extract the mode checking and
+assignment logic into common functions.
+
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Reviewed-by: Oleg Nesterov <oleg@redhat.com>
+Reviewed-by: Andy Lutomirski <luto@amacapital.net>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ kernel/seccomp.c | 22 ++++++++++++++++++----
+ 1 file changed, 18 insertions(+), 4 deletions(-)
+
+--- a/kernel/seccomp.c
++++ b/kernel/seccomp.c
+@@ -194,7 +194,23 @@ static u32 seccomp_run_filters(int sysca
+ }
+ return ret;
+ }
++#endif /* CONFIG_SECCOMP_FILTER */
+
++static inline bool seccomp_may_assign_mode(unsigned long seccomp_mode)
++{
++ if (current->seccomp.mode && current->seccomp.mode != seccomp_mode)
++ return false;
++
++ return true;
++}
++
++static inline void seccomp_assign_mode(unsigned long seccomp_mode)
++{
++ current->seccomp.mode = seccomp_mode;
++ set_tsk_thread_flag(current, TIF_SECCOMP);
++}
++
++#ifdef CONFIG_SECCOMP_FILTER
+ /**
+ * seccomp_attach_filter: Attaches a seccomp filter to current.
+ * @fprog: BPF program to install
+@@ -490,8 +506,7 @@ static long seccomp_set_mode(unsigned lo
+ {
+ long ret = -EINVAL;
+
+- if (current->seccomp.mode &&
+- current->seccomp.mode != seccomp_mode)
++ if (!seccomp_may_assign_mode(seccomp_mode))
+ goto out;
+
+ switch (seccomp_mode) {
+@@ -512,8 +527,7 @@ static long seccomp_set_mode(unsigned lo
+ goto out;
+ }
+
+- current->seccomp.mode = seccomp_mode;
+- set_thread_flag(TIF_SECCOMP);
++ seccomp_assign_mode(seccomp_mode);
+ out:
+ return ret;
+ }
diff --git a/queue-3.16/seccomp-split-mode-setting-routines.patch b/queue-3.16/seccomp-split-mode-setting-routines.patch
new file mode 100644
index 00000000..78047cfa
--- /dev/null
+++ b/queue-3.16/seccomp-split-mode-setting-routines.patch
@@ -0,0 +1,122 @@
+From: Kees Cook <keescook@chromium.org>
+Date: Wed, 25 Jun 2014 15:55:25 -0700
+Subject: seccomp: split mode setting routines
+
+commit 3b23dd12846215eff4afb073366b80c0c4d7543e upstream.
+
+Separates the two mode setting paths to make things more readable with
+fewer #ifdefs within function bodies.
+
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Reviewed-by: Oleg Nesterov <oleg@redhat.com>
+Reviewed-by: Andy Lutomirski <luto@amacapital.net>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ kernel/seccomp.c | 71 ++++++++++++++++++++++++++++++++----------------
+ 1 file changed, 48 insertions(+), 23 deletions(-)
+
+--- a/kernel/seccomp.c
++++ b/kernel/seccomp.c
+@@ -489,48 +489,66 @@ long prctl_get_seccomp(void)
+ }
+
+ /**
+- * seccomp_set_mode: internal function for setting seccomp mode
+- * @seccomp_mode: requested mode to use
+- * @filter: optional struct sock_fprog for use with SECCOMP_MODE_FILTER
+- *
+- * This function may be called repeatedly with a @seccomp_mode of
+- * SECCOMP_MODE_FILTER to install additional filters. Every filter
+- * successfully installed will be evaluated (in reverse order) for each system
+- * call the task makes.
++ * seccomp_set_mode_strict: internal function for setting strict seccomp
+ *
+ * Once current->seccomp.mode is non-zero, it may not be changed.
+ *
+ * Returns 0 on success or -EINVAL on failure.
+ */
+-static long seccomp_set_mode(unsigned long seccomp_mode, char __user *filter)
++static long seccomp_set_mode_strict(void)
+ {
++ const unsigned long seccomp_mode = SECCOMP_MODE_STRICT;
+ long ret = -EINVAL;
+
+ if (!seccomp_may_assign_mode(seccomp_mode))
+ goto out;
+
+- switch (seccomp_mode) {
+- case SECCOMP_MODE_STRICT:
+- ret = 0;
+ #ifdef TIF_NOTSC
+- disable_TSC();
++ disable_TSC();
+ #endif
+- break;
++ seccomp_assign_mode(seccomp_mode);
++ ret = 0;
++
++out:
++
++ return ret;
++}
++
+ #ifdef CONFIG_SECCOMP_FILTER
+- case SECCOMP_MODE_FILTER:
+- ret = seccomp_attach_user_filter(filter);
+- if (ret)
+- goto out;
+- break;
+-#endif
+- default:
++/**
++ * seccomp_set_mode_filter: internal function for setting seccomp filter
++ * @filter: struct sock_fprog containing filter
++ *
++ * This function may be called repeatedly to install additional filters.
++ * Every filter successfully installed will be evaluated (in reverse order)
++ * for each system call the task makes.
++ *
++ * Once current->seccomp.mode is non-zero, it may not be changed.
++ *
++ * Returns 0 on success or -EINVAL on failure.
++ */
++static long seccomp_set_mode_filter(char __user *filter)
++{
++ const unsigned long seccomp_mode = SECCOMP_MODE_FILTER;
++ long ret = -EINVAL;
++
++ if (!seccomp_may_assign_mode(seccomp_mode))
++ goto out;
++
++ ret = seccomp_attach_user_filter(filter);
++ if (ret)
+ goto out;
+- }
+
+ seccomp_assign_mode(seccomp_mode);
+ out:
+ return ret;
+ }
++#else
++static inline long seccomp_set_mode_filter(char __user *filter)
++{
++ return -EINVAL;
++}
++#endif
+
+ /**
+ * prctl_set_seccomp: configures current->seccomp.mode
+@@ -541,5 +559,12 @@ out:
+ */
+ long prctl_set_seccomp(unsigned long seccomp_mode, char __user *filter)
+ {
+- return seccomp_set_mode(seccomp_mode, filter);
++ switch (seccomp_mode) {
++ case SECCOMP_MODE_STRICT:
++ return seccomp_set_mode_strict();
++ case SECCOMP_MODE_FILTER:
++ return seccomp_set_mode_filter(filter);
++ default:
++ return -EINVAL;
++ }
+ }
diff --git a/queue-3.16/series b/queue-3.16/series
index 7129c88b..1ccd2dc7 100644
--- a/queue-3.16/series
+++ b/queue-3.16/series
@@ -51,3 +51,7 @@ hfsplus-fix-null-dereference-in-hfsplus_lookup.patch
xfs-catch-inode-allocation-state-mismatch-corruption.patch
xfs-validate-cached-inodes-are-free-when-allocated.patch
xfs-don-t-call-xfs_da_shrink_inode-with-null-bp.patch
+seccomp-create-internal-mode-setting-function.patch
+seccomp-extract-check-assign-mode-helpers.patch
+seccomp-split-mode-setting-routines.patch
+seccomp-add-seccomp-syscall.patch