diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.9.21/0050-prctl-Add-force-disable-speculation.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.9.21/0050-prctl-Add-force-disable-speculation.patch | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.9.21/0050-prctl-Add-force-disable-speculation.patch b/common/recipes-kernel/linux/linux-yocto-4.9.21/0050-prctl-Add-force-disable-speculation.patch new file mode 100644 index 00000000..acdc260b --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.9.21/0050-prctl-Add-force-disable-speculation.patch @@ -0,0 +1,218 @@ +From 6eca73ee80c5d8b6f8c3d294b3f97b7c8da67791 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner <tglx@linutronix.de> +Date: Thu, 3 May 2018 22:09:15 +0200 +Subject: [PATCH 50/93] prctl: Add force disable speculation + +commit 356e4bfff2c5489e016fdb925adbf12a1e3950ee upstream + +For certain use cases it is desired to enforce mitigations so they cannot +be undone afterwards. That's important for loader stubs which want to +prevent a child from disabling the mitigation again. Will also be used for +seccomp(). The extra state preserving of the prctl state for SSB is a +preparatory step for EBPF dymanic speculation control. + +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> +--- + Documentation/spec_ctrl.txt | 34 +++++++++++++++++++++------------- + arch/x86/kernel/cpu/bugs.c | 35 +++++++++++++++++++++++++---------- + fs/proc/array.c | 3 +++ + include/linux/sched.h | 9 +++++++++ + include/uapi/linux/prctl.h | 1 + + 5 files changed, 59 insertions(+), 23 deletions(-) + +diff --git a/Documentation/spec_ctrl.txt b/Documentation/spec_ctrl.txt +index ddbebcd..1b3690d 100644 +--- a/Documentation/spec_ctrl.txt ++++ b/Documentation/spec_ctrl.txt +@@ -25,19 +25,21 @@ PR_GET_SPECULATION_CTRL + ----------------------- + + PR_GET_SPECULATION_CTRL returns the state of the speculation misfeature +-which is selected with arg2 of prctl(2). The return value uses bits 0-2 with ++which is selected with arg2 of prctl(2). The return value uses bits 0-3 with + the following meaning: + +-==== ================ =================================================== +-Bit Define Description +-==== ================ =================================================== +-0 PR_SPEC_PRCTL Mitigation can be controlled per task by +- PR_SET_SPECULATION_CTRL +-1 PR_SPEC_ENABLE The speculation feature is enabled, mitigation is +- disabled +-2 PR_SPEC_DISABLE The speculation feature is disabled, mitigation is +- enabled +-==== ================ =================================================== ++==== ===================== =================================================== ++Bit Define Description ++==== ===================== =================================================== ++0 PR_SPEC_PRCTL Mitigation can be controlled per task by ++ PR_SET_SPECULATION_CTRL ++1 PR_SPEC_ENABLE The speculation feature is enabled, mitigation is ++ disabled ++2 PR_SPEC_DISABLE The speculation feature is disabled, mitigation is ++ enabled ++3 PR_SPEC_FORCE_DISABLE Same as PR_SPEC_DISABLE, but cannot be undone. A ++ subsequent prctl(..., PR_SPEC_ENABLE) will fail. ++==== ===================== =================================================== + + If all bits are 0 the CPU is not affected by the speculation misfeature. + +@@ -47,9 +49,11 @@ misfeature will fail. + + PR_SET_SPECULATION_CTRL + ----------------------- ++ + PR_SET_SPECULATION_CTRL allows to control the speculation misfeature, which + is selected by arg2 of :manpage:`prctl(2)` per task. arg3 is used to hand +-in the control value, i.e. either PR_SPEC_ENABLE or PR_SPEC_DISABLE. ++in the control value, i.e. either PR_SPEC_ENABLE or PR_SPEC_DISABLE or ++PR_SPEC_FORCE_DISABLE. + + Common error codes + ------------------ +@@ -70,10 +74,13 @@ Value Meaning + 0 Success + + ERANGE arg3 is incorrect, i.e. it's neither PR_SPEC_ENABLE nor +- PR_SPEC_DISABLE ++ PR_SPEC_DISABLE nor PR_SPEC_FORCE_DISABLE + + ENXIO Control of the selected speculation misfeature is not possible. + See PR_GET_SPECULATION_CTRL. ++ ++EPERM Speculation was disabled with PR_SPEC_FORCE_DISABLE and caller ++ tried to enable it again. + ======= ================================================================= + + Speculation misfeature controls +@@ -84,3 +91,4 @@ Speculation misfeature controls + * prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, 0, 0, 0); + * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_ENABLE, 0, 0); + * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE, 0, 0); ++ * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_FORCE_DISABLE, 0, 0); +diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c +index 65114d2..fdbd8e5 100644 +--- a/arch/x86/kernel/cpu/bugs.c ++++ b/arch/x86/kernel/cpu/bugs.c +@@ -532,21 +532,37 @@ static void ssb_select_mitigation() + + static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl) + { +- bool rds = !!test_tsk_thread_flag(task, TIF_RDS); ++ bool update; + + if (ssb_mode != SPEC_STORE_BYPASS_PRCTL) + return -ENXIO; + +- if (ctrl == PR_SPEC_ENABLE) +- clear_tsk_thread_flag(task, TIF_RDS); +- else +- set_tsk_thread_flag(task, TIF_RDS); ++ switch (ctrl) { ++ case PR_SPEC_ENABLE: ++ /* If speculation is force disabled, enable is not allowed */ ++ if (task_spec_ssb_force_disable(task)) ++ return -EPERM; ++ task_clear_spec_ssb_disable(task); ++ update = test_and_clear_tsk_thread_flag(task, TIF_RDS); ++ break; ++ case PR_SPEC_DISABLE: ++ task_set_spec_ssb_disable(task); ++ update = !test_and_set_tsk_thread_flag(task, TIF_RDS); ++ break; ++ case PR_SPEC_FORCE_DISABLE: ++ task_set_spec_ssb_disable(task); ++ task_set_spec_ssb_force_disable(task); ++ update = !test_and_set_tsk_thread_flag(task, TIF_RDS); ++ break; ++ default: ++ return -ERANGE; ++ } + + /* + * 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)) ++ if (task == current && update) + speculative_store_bypass_update(); + + return 0; +@@ -558,7 +574,9 @@ static int ssb_prctl_get(struct task_struct *task) + case SPEC_STORE_BYPASS_DISABLE: + return PR_SPEC_DISABLE; + case SPEC_STORE_BYPASS_PRCTL: +- if (test_tsk_thread_flag(task, TIF_RDS)) ++ if (task_spec_ssb_force_disable(task)) ++ return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE; ++ if (task_spec_ssb_disable(task)) + return PR_SPEC_PRCTL | PR_SPEC_DISABLE; + return PR_SPEC_PRCTL | PR_SPEC_ENABLE; + default: +@@ -571,9 +589,6 @@ static int ssb_prctl_get(struct task_struct *task) + 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(task, ctrl); +diff --git a/fs/proc/array.c b/fs/proc/array.c +index 64f3f20..3e37195 100644 +--- a/fs/proc/array.c ++++ b/fs/proc/array.c +@@ -355,6 +355,9 @@ static inline void task_seccomp(struct seq_file *m, struct task_struct *p) + case PR_SPEC_NOT_AFFECTED: + seq_printf(m, "not vulnerable"); + break; ++ case PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE: ++ seq_printf(m, "thread force mitigated"); ++ break; + case PR_SPEC_PRCTL | PR_SPEC_DISABLE: + seq_printf(m, "thread mitigated"); + break; +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 75d9a57..8e127a3 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -2335,6 +2335,8 @@ static inline void memalloc_noio_restore(unsigned int flags) + #define PFA_SPREAD_PAGE 1 /* Spread page cache over cpuset */ + #define PFA_SPREAD_SLAB 2 /* Spread some slab caches over cpuset */ + #define PFA_LMK_WAITING 3 /* Lowmemorykiller is waiting */ ++#define PFA_SPEC_SSB_DISABLE 4 /* Speculative Store Bypass disabled */ ++#define PFA_SPEC_SSB_FORCE_DISABLE 5 /* Speculative Store Bypass force disabled*/ + + + #define TASK_PFA_TEST(name, func) \ +@@ -2361,6 +2363,13 @@ TASK_PFA_CLEAR(SPREAD_SLAB, spread_slab) + TASK_PFA_TEST(LMK_WAITING, lmk_waiting) + TASK_PFA_SET(LMK_WAITING, lmk_waiting) + ++TASK_PFA_TEST(SPEC_SSB_DISABLE, spec_ssb_disable) ++TASK_PFA_SET(SPEC_SSB_DISABLE, spec_ssb_disable) ++TASK_PFA_CLEAR(SPEC_SSB_DISABLE, spec_ssb_disable) ++ ++TASK_PFA_TEST(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable) ++TASK_PFA_SET(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable) ++ + /* + * task->jobctl flags + */ +diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h +index 3b316be..64776b7 100644 +--- a/include/uapi/linux/prctl.h ++++ b/include/uapi/linux/prctl.h +@@ -207,5 +207,6 @@ struct prctl_mm_map { + # define PR_SPEC_PRCTL (1UL << 0) + # define PR_SPEC_ENABLE (1UL << 1) + # define PR_SPEC_DISABLE (1UL << 2) ++# define PR_SPEC_FORCE_DISABLE (1UL << 3) + + #endif /* _LINUX_PRCTL_H */ +-- +2.7.4 + |