aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2018-11-28 04:56:57 -0500
committerThomas Gleixner <tglx@linutronix.de>2018-11-28 05:57:12 -0500
commit6d991ba509ebcfcc908e009d1db51972a4f7a064 (patch)
tree00229ed13c98a3ec81448ab1e43476888669e6dc
parente6da8bb6f9abb2628381904b24163c770e630bac (diff)
x86/speculation: Prevent stale SPEC_CTRL msr content
The seccomp speculation control operates on all tasks of a process, but only the current task of a process can update the MSR immediately. For the other threads the update is deferred to the next context switch. This creates the following situation with Process A and B: Process A task 2 and Process B task 1 are pinned on CPU1. Process A task 2 does not have the speculation control TIF bit set. Process B task 1 has the speculation control TIF bit set. CPU0 CPU1 MSR bit is set ProcB.T1 schedules out ProcA.T2 schedules in MSR bit is cleared ProcA.T1 seccomp_update() set TIF bit on ProcA.T2 ProcB.T1 schedules in MSR is not updated <-- FAIL This happens because the context switch code tries to avoid the MSR update if the speculation control TIF bits of the incoming and the outgoing task are the same. In the worst case ProcB.T1 and ProcA.T2 are the only tasks scheduling back and forth on CPU1, which keeps the MSR stale forever. In theory this could be remedied by IPIs, but chasing the remote task which could be migrated is complex and full of races. The straight forward solution is to avoid the asychronous update of the TIF bit and defer it to the next context switch. The speculation control state is stored in task_struct::atomic_flags by the prctl and seccomp updates already. Add a new TIF_SPEC_FORCE_UPDATE bit and set this after updating the atomic_flags. Check the bit on context switch and force a synchronous update of the speculation control if set. Use the same mechanism for updating the current task. Reported-by: Tim Chen <tim.c.chen@linux.intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Andy Lutomirski <luto@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Jiri Kosina <jkosina@suse.cz> Cc: Tom Lendacky <thomas.lendacky@amd.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: David Woodhouse <dwmw@amazon.co.uk> Cc: Tim Chen <tim.c.chen@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Casey Schaufler <casey.schaufler@intel.com> Cc: Asit Mallick <asit.k.mallick@intel.com> Cc: Arjan van de Ven <arjan@linux.intel.com> Cc: Jon Masters <jcm@redhat.com> Cc: Waiman Long <longman9394@gmail.com> Cc: Greg KH <gregkh@linuxfoundation.org> Cc: Dave Stewart <david.c.stewart@intel.com> Cc: Kees Cook <keescook@chromium.org> Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/alpine.DEB.2.21.1811272247140.1875@nanos.tec.linutronix.de
-rw-r--r--arch/x86/include/asm/spec-ctrl.h6
-rw-r--r--arch/x86/include/asm/thread_info.h4
-rw-r--r--arch/x86/kernel/cpu/bugs.c18
-rw-r--r--arch/x86/kernel/process.c30
4 files changed, 40 insertions, 18 deletions
diff --git a/arch/x86/include/asm/spec-ctrl.h b/arch/x86/include/asm/spec-ctrl.h
index 27b0bce3933b..5393babc0598 100644
--- a/arch/x86/include/asm/spec-ctrl.h
+++ b/arch/x86/include/asm/spec-ctrl.h
@@ -83,10 +83,6 @@ static inline void speculative_store_bypass_ht_init(void) { }
83#endif 83#endif
84 84
85extern void speculation_ctrl_update(unsigned long tif); 85extern void speculation_ctrl_update(unsigned long tif);
86 86extern void speculation_ctrl_update_current(void);
87static inline void speculation_ctrl_update_current(void)
88{
89 speculation_ctrl_update(current_thread_info()->flags);
90}
91 87
92#endif 88#endif
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index 6d201699c651..82b73b75d67c 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -84,6 +84,7 @@ struct thread_info {
84#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ 84#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
85#define TIF_SECCOMP 8 /* secure computing */ 85#define TIF_SECCOMP 8 /* secure computing */
86#define TIF_SPEC_IB 9 /* Indirect branch speculation mitigation */ 86#define TIF_SPEC_IB 9 /* Indirect branch speculation mitigation */
87#define TIF_SPEC_FORCE_UPDATE 10 /* Force speculation MSR update in context switch */
87#define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */ 88#define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */
88#define TIF_UPROBE 12 /* breakpointed or singlestepping */ 89#define TIF_UPROBE 12 /* breakpointed or singlestepping */
89#define TIF_PATCH_PENDING 13 /* pending live patching update */ 90#define TIF_PATCH_PENDING 13 /* pending live patching update */
@@ -112,6 +113,7 @@ struct thread_info {
112#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) 113#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
113#define _TIF_SECCOMP (1 << TIF_SECCOMP) 114#define _TIF_SECCOMP (1 << TIF_SECCOMP)
114#define _TIF_SPEC_IB (1 << TIF_SPEC_IB) 115#define _TIF_SPEC_IB (1 << TIF_SPEC_IB)
116#define _TIF_SPEC_FORCE_UPDATE (1 << TIF_SPEC_FORCE_UPDATE)
115#define _TIF_USER_RETURN_NOTIFY (1 << TIF_USER_RETURN_NOTIFY) 117#define _TIF_USER_RETURN_NOTIFY (1 << TIF_USER_RETURN_NOTIFY)
116#define _TIF_UPROBE (1 << TIF_UPROBE) 118#define _TIF_UPROBE (1 << TIF_UPROBE)
117#define _TIF_PATCH_PENDING (1 << TIF_PATCH_PENDING) 119#define _TIF_PATCH_PENDING (1 << TIF_PATCH_PENDING)
@@ -149,7 +151,7 @@ struct thread_info {
149/* flags to check in __switch_to() */ 151/* flags to check in __switch_to() */
150#define _TIF_WORK_CTXSW_BASE \ 152#define _TIF_WORK_CTXSW_BASE \
151 (_TIF_IO_BITMAP|_TIF_NOCPUID|_TIF_NOTSC|_TIF_BLOCKSTEP| \ 153 (_TIF_IO_BITMAP|_TIF_NOCPUID|_TIF_NOTSC|_TIF_BLOCKSTEP| \
152 _TIF_SSBD) 154 _TIF_SSBD | _TIF_SPEC_FORCE_UPDATE)
153 155
154/* 156/*
155 * Avoid calls to __switch_to_xtra() on UP as STIBP is not evaluated. 157 * Avoid calls to __switch_to_xtra() on UP as STIBP is not evaluated.
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 3b65a53d2c33..29f40a92f5a8 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -702,14 +702,10 @@ static void ssb_select_mitigation(void)
702#undef pr_fmt 702#undef pr_fmt
703#define pr_fmt(fmt) "Speculation prctl: " fmt 703#define pr_fmt(fmt) "Speculation prctl: " fmt
704 704
705static void task_update_spec_tif(struct task_struct *tsk, int tifbit, bool on) 705static void task_update_spec_tif(struct task_struct *tsk)
706{ 706{
707 bool update; 707 /* Force the update of the real TIF bits */
708 708 set_tsk_thread_flag(tsk, TIF_SPEC_FORCE_UPDATE);
709 if (on)
710 update = !test_and_set_tsk_thread_flag(tsk, tifbit);
711 else
712 update = test_and_clear_tsk_thread_flag(tsk, tifbit);
713 709
714 /* 710 /*
715 * Immediately update the speculation control MSRs for the current 711 * Immediately update the speculation control MSRs for the current
@@ -719,7 +715,7 @@ static void task_update_spec_tif(struct task_struct *tsk, int tifbit, bool on)
719 * This can only happen for SECCOMP mitigation. For PRCTL it's 715 * This can only happen for SECCOMP mitigation. For PRCTL it's
720 * always the current task. 716 * always the current task.
721 */ 717 */
722 if (tsk == current && update) 718 if (tsk == current)
723 speculation_ctrl_update_current(); 719 speculation_ctrl_update_current();
724} 720}
725 721
@@ -735,16 +731,16 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
735 if (task_spec_ssb_force_disable(task)) 731 if (task_spec_ssb_force_disable(task))
736 return -EPERM; 732 return -EPERM;
737 task_clear_spec_ssb_disable(task); 733 task_clear_spec_ssb_disable(task);
738 task_update_spec_tif(task, TIF_SSBD, false); 734 task_update_spec_tif(task);
739 break; 735 break;
740 case PR_SPEC_DISABLE: 736 case PR_SPEC_DISABLE:
741 task_set_spec_ssb_disable(task); 737 task_set_spec_ssb_disable(task);
742 task_update_spec_tif(task, TIF_SSBD, true); 738 task_update_spec_tif(task);
743 break; 739 break;
744 case PR_SPEC_FORCE_DISABLE: 740 case PR_SPEC_FORCE_DISABLE:
745 task_set_spec_ssb_disable(task); 741 task_set_spec_ssb_disable(task);
746 task_set_spec_ssb_force_disable(task); 742 task_set_spec_ssb_force_disable(task);
747 task_update_spec_tif(task, TIF_SSBD, true); 743 task_update_spec_tif(task);
748 break; 744 break;
749 default: 745 default:
750 return -ERANGE; 746 return -ERANGE;
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index cdf8e6694f71..afbe2eb4a1c6 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -443,6 +443,18 @@ static __always_inline void __speculation_ctrl_update(unsigned long tifp,
443 wrmsrl(MSR_IA32_SPEC_CTRL, msr); 443 wrmsrl(MSR_IA32_SPEC_CTRL, msr);
444} 444}
445 445
446static unsigned long speculation_ctrl_update_tif(struct task_struct *tsk)
447{
448 if (test_and_clear_tsk_thread_flag(tsk, TIF_SPEC_FORCE_UPDATE)) {
449 if (task_spec_ssb_disable(tsk))
450 set_tsk_thread_flag(tsk, TIF_SSBD);
451 else
452 clear_tsk_thread_flag(tsk, TIF_SSBD);
453 }
454 /* Return the updated threadinfo flags*/
455 return task_thread_info(tsk)->flags;
456}
457
446void speculation_ctrl_update(unsigned long tif) 458void speculation_ctrl_update(unsigned long tif)
447{ 459{
448 /* Forced update. Make sure all relevant TIF flags are different */ 460 /* Forced update. Make sure all relevant TIF flags are different */
@@ -451,6 +463,14 @@ void speculation_ctrl_update(unsigned long tif)
451 preempt_enable(); 463 preempt_enable();
452} 464}
453 465
466/* Called from seccomp/prctl update */
467void speculation_ctrl_update_current(void)
468{
469 preempt_disable();
470 speculation_ctrl_update(speculation_ctrl_update_tif(current));
471 preempt_enable();
472}
473
454void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p) 474void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
455{ 475{
456 struct thread_struct *prev, *next; 476 struct thread_struct *prev, *next;
@@ -482,7 +502,15 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
482 if ((tifp ^ tifn) & _TIF_NOCPUID) 502 if ((tifp ^ tifn) & _TIF_NOCPUID)
483 set_cpuid_faulting(!!(tifn & _TIF_NOCPUID)); 503 set_cpuid_faulting(!!(tifn & _TIF_NOCPUID));
484 504
485 __speculation_ctrl_update(tifp, tifn); 505 if (likely(!((tifp | tifn) & _TIF_SPEC_FORCE_UPDATE))) {
506 __speculation_ctrl_update(tifp, tifn);
507 } else {
508 speculation_ctrl_update_tif(prev_p);
509 tifn = speculation_ctrl_update_tif(next_p);
510
511 /* Enforce MSR update to ensure consistent state */
512 __speculation_ctrl_update(~tifn, tifn);
513 }
486} 514}
487 515
488/* 516/*