diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.9.21/0045-nospec-Allow-getting-setting-on-non-current-task.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.9.21/0045-nospec-Allow-getting-setting-on-non-current-task.patch | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.9.21/0045-nospec-Allow-getting-setting-on-non-current-task.patch b/common/recipes-kernel/linux/linux-yocto-4.9.21/0045-nospec-Allow-getting-setting-on-non-current-task.patch new file mode 100644 index 00000000..5c1e6d48 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.9.21/0045-nospec-Allow-getting-setting-on-non-current-task.patch @@ -0,0 +1,162 @@ +From e2a9a40a2a4fbebc999eacc678c2af449db5af11 Mon Sep 17 00:00:00 2001 +From: Kees Cook <keescook@chromium.org> +Date: Tue, 1 May 2018 15:19:04 -0700 +Subject: [PATCH 45/93] nospec: Allow getting/setting on non-current task + +commit 7bbf1373e228840bb0295a2ca26d548ef37f448e upstream + +Adjust arch_prctl_get/set_spec_ctrl() to operate on tasks other than +current. + +This is needed both for /proc/$pid/status queries and for seccomp (since +thread-syncing can trigger seccomp in non-current threads). + +Signed-off-by: Kees Cook <keescook@chromium.org> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + arch/x86/kernel/cpu/bugs.c | 27 ++++++++++++++++----------- + include/linux/nospec.h | 7 +++++-- + kernel/sys.c | 9 +++++---- + 3 files changed, 26 insertions(+), 17 deletions(-) + +diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c +index b7d9adf..3760931 100644 +--- a/arch/x86/kernel/cpu/bugs.c ++++ b/arch/x86/kernel/cpu/bugs.c +@@ -529,31 +529,35 @@ static void ssb_select_mitigation() + + #undef pr_fmt + +-static int ssb_prctl_set(unsigned long ctrl) ++static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl) + { +- bool rds = !!test_tsk_thread_flag(current, TIF_RDS); ++ bool rds = !!test_tsk_thread_flag(task, TIF_RDS); + + if (ssb_mode != SPEC_STORE_BYPASS_PRCTL) + return -ENXIO; + + if (ctrl == PR_SPEC_ENABLE) +- clear_tsk_thread_flag(current, TIF_RDS); ++ clear_tsk_thread_flag(task, TIF_RDS); + else +- set_tsk_thread_flag(current, TIF_RDS); ++ set_tsk_thread_flag(task, TIF_RDS); + +- if (rds != !!test_tsk_thread_flag(current, TIF_RDS)) ++ /* ++ * If being set on non-current task, delay setting the CPU ++ * mitigation until it is next scheduled. ++ */ ++ if (task == current && rds != !!test_tsk_thread_flag(task, TIF_RDS)) + speculative_store_bypass_update(); + + return 0; + } + +-static int ssb_prctl_get(void) ++static int ssb_prctl_get(struct task_struct *task) + { + switch (ssb_mode) { + case SPEC_STORE_BYPASS_DISABLE: + return PR_SPEC_DISABLE; + case SPEC_STORE_BYPASS_PRCTL: +- if (test_tsk_thread_flag(current, TIF_RDS)) ++ if (test_tsk_thread_flag(task, TIF_RDS)) + return PR_SPEC_PRCTL | PR_SPEC_DISABLE; + return PR_SPEC_PRCTL | PR_SPEC_ENABLE; + default: +@@ -563,24 +567,25 @@ static int ssb_prctl_get(void) + } + } + +-int arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl) ++int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which, ++ unsigned long ctrl) + { + if (ctrl != PR_SPEC_ENABLE && ctrl != PR_SPEC_DISABLE) + return -ERANGE; + + switch (which) { + case PR_SPEC_STORE_BYPASS: +- return ssb_prctl_set(ctrl); ++ return ssb_prctl_set(task, ctrl); + default: + return -ENODEV; + } + } + +-int arch_prctl_spec_ctrl_get(unsigned long which) ++int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which) + { + switch (which) { + case PR_SPEC_STORE_BYPASS: +- return ssb_prctl_get(); ++ return ssb_prctl_get(task); + default: + return -ENODEV; + } +diff --git a/include/linux/nospec.h b/include/linux/nospec.h +index 700bb8a..a908c95 100644 +--- a/include/linux/nospec.h ++++ b/include/linux/nospec.h +@@ -7,6 +7,8 @@ + #define _LINUX_NOSPEC_H + #include <asm/barrier.h> + ++struct task_struct; ++ + /** + * array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise + * @index: array element index +@@ -57,7 +59,8 @@ static inline unsigned long array_index_mask_nospec(unsigned long index, + }) + + /* Speculation control prctl */ +-int arch_prctl_spec_ctrl_get(unsigned long which); +-int arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl); ++int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which); ++int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which, ++ unsigned long ctrl); + + #endif /* _LINUX_NOSPEC_H */ +diff --git a/kernel/sys.c b/kernel/sys.c +index 312c985..143cd63 100644 +--- a/kernel/sys.c ++++ b/kernel/sys.c +@@ -2074,12 +2074,13 @@ static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr) + } + #endif + +-int __weak arch_prctl_spec_ctrl_get(unsigned long which) ++int __weak arch_prctl_spec_ctrl_get(struct task_struct *t, unsigned long which) + { + return -EINVAL; + } + +-int __weak arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl) ++int __weak arch_prctl_spec_ctrl_set(struct task_struct *t, unsigned long which, ++ unsigned long ctrl) + { + return -EINVAL; + } +@@ -2285,12 +2286,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, + case PR_GET_SPECULATION_CTRL: + if (arg3 || arg4 || arg5) + return -EINVAL; +- error = arch_prctl_spec_ctrl_get(arg2); ++ error = arch_prctl_spec_ctrl_get(me, arg2); + break; + case PR_SET_SPECULATION_CTRL: + if (arg4 || arg5) + return -EINVAL; +- error = arch_prctl_spec_ctrl_set(arg2, arg3); ++ error = arch_prctl_spec_ctrl_set(me, arg2, arg3); + break; + default: + error = -EINVAL; +-- +2.7.4 + |