diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2018-09-16 16:51:10 +0100 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2018-09-16 16:51:10 +0100 |
commit | eda6678bf03971d7a46e6937cdfecdbbf10e83c8 (patch) | |
tree | f8956a876700887521e53cddb587ea82b248ce8d /queue-3.16 | |
parent | 58b9e960c0380f6ccb913c02968bbaed905bce82 (diff) | |
download | linux-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.patch | 220 | ||||
-rw-r--r-- | queue-3.16/seccomp-create-internal-mode-setting-function.patch | 54 | ||||
-rw-r--r-- | queue-3.16/seccomp-extract-check-assign-mode-helpers.patch | 63 | ||||
-rw-r--r-- | queue-3.16/seccomp-split-mode-setting-routines.patch | 122 | ||||
-rw-r--r-- | queue-3.16/series | 4 |
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 |