summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2018-11-25 13:33:53 -0500
committerThomas Gleixner <tglx@linutronix.de>2018-11-28 05:57:13 -0500
commit9137bb27e60e554dab694eafa4cca241fa3a694f (patch)
tree210ca811947bb90452df9f8a3752402e6252a530
parent6893a959d7fdebbab5f5aa112c277d5a44435ba1 (diff)
x86/speculation: Add prctl() control for indirect branch speculation
Add the PR_SPEC_INDIRECT_BRANCH option for the PR_GET_SPECULATION_CTRL and PR_SET_SPECULATION_CTRL prctls to allow fine grained per task control of indirect branch speculation via STIBP and IBPB. Invocations: Check indirect branch speculation status with - prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, 0, 0, 0); Enable indirect branch speculation with - prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_ENABLE, 0, 0); Disable indirect branch speculation with - prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_DISABLE, 0, 0); Force disable indirect branch speculation with - prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_FORCE_DISABLE, 0, 0); See Documentation/userspace-api/spec_ctrl.rst. Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Ingo Molnar <mingo@kernel.org> 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: 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/20181125185005.866780996@linutronix.de
-rw-r--r--Documentation/userspace-api/spec_ctrl.rst9
-rw-r--r--arch/x86/include/asm/nospec-branch.h1
-rw-r--r--arch/x86/kernel/cpu/bugs.c67
-rw-r--r--arch/x86/kernel/process.c5
-rw-r--r--include/linux/sched.h9
-rw-r--r--include/uapi/linux/prctl.h1
-rw-r--r--tools/include/uapi/linux/prctl.h1
7 files changed, 93 insertions, 0 deletions
diff --git a/Documentation/userspace-api/spec_ctrl.rst b/Documentation/userspace-api/spec_ctrl.rst
index 32f3d55c54b7..c4dbe6f7cdae 100644
--- a/Documentation/userspace-api/spec_ctrl.rst
+++ b/Documentation/userspace-api/spec_ctrl.rst
@@ -92,3 +92,12 @@ Speculation misfeature controls
92 * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_ENABLE, 0, 0); 92 * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_ENABLE, 0, 0);
93 * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE, 0, 0); 93 * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE, 0, 0);
94 * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_FORCE_DISABLE, 0, 0); 94 * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_FORCE_DISABLE, 0, 0);
95
96- PR_SPEC_INDIR_BRANCH: Indirect Branch Speculation in User Processes
97 (Mitigate Spectre V2 style attacks against user processes)
98
99 Invocations:
100 * prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, 0, 0, 0);
101 * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_ENABLE, 0, 0);
102 * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_DISABLE, 0, 0);
103 * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_FORCE_DISABLE, 0, 0);
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index d4d35baf0430..2adbe7b047fa 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -232,6 +232,7 @@ enum spectre_v2_mitigation {
232enum spectre_v2_user_mitigation { 232enum spectre_v2_user_mitigation {
233 SPECTRE_V2_USER_NONE, 233 SPECTRE_V2_USER_NONE,
234 SPECTRE_V2_USER_STRICT, 234 SPECTRE_V2_USER_STRICT,
235 SPECTRE_V2_USER_PRCTL,
235}; 236};
236 237
237/* The Speculative Store Bypass disable variants */ 238/* The Speculative Store Bypass disable variants */
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 9cab538e10f1..74359fff87fd 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -566,6 +566,8 @@ void arch_smt_update(void)
566 case SPECTRE_V2_USER_STRICT: 566 case SPECTRE_V2_USER_STRICT:
567 update_stibp_strict(); 567 update_stibp_strict();
568 break; 568 break;
569 case SPECTRE_V2_USER_PRCTL:
570 break;
569 } 571 }
570 572
571 mutex_unlock(&spec_ctrl_mutex); 573 mutex_unlock(&spec_ctrl_mutex);
@@ -752,12 +754,50 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
752 return 0; 754 return 0;
753} 755}
754 756
757static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
758{
759 switch (ctrl) {
760 case PR_SPEC_ENABLE:
761 if (spectre_v2_user == SPECTRE_V2_USER_NONE)
762 return 0;
763 /*
764 * Indirect branch speculation is always disabled in strict
765 * mode.
766 */
767 if (spectre_v2_user == SPECTRE_V2_USER_STRICT)
768 return -EPERM;
769 task_clear_spec_ib_disable(task);
770 task_update_spec_tif(task);
771 break;
772 case PR_SPEC_DISABLE:
773 case PR_SPEC_FORCE_DISABLE:
774 /*
775 * Indirect branch speculation is always allowed when
776 * mitigation is force disabled.
777 */
778 if (spectre_v2_user == SPECTRE_V2_USER_NONE)
779 return -EPERM;
780 if (spectre_v2_user == SPECTRE_V2_USER_STRICT)
781 return 0;
782 task_set_spec_ib_disable(task);
783 if (ctrl == PR_SPEC_FORCE_DISABLE)
784 task_set_spec_ib_force_disable(task);
785 task_update_spec_tif(task);
786 break;
787 default:
788 return -ERANGE;
789 }
790 return 0;
791}
792
755int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which, 793int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
756 unsigned long ctrl) 794 unsigned long ctrl)
757{ 795{
758 switch (which) { 796 switch (which) {
759 case PR_SPEC_STORE_BYPASS: 797 case PR_SPEC_STORE_BYPASS:
760 return ssb_prctl_set(task, ctrl); 798 return ssb_prctl_set(task, ctrl);
799 case PR_SPEC_INDIRECT_BRANCH:
800 return ib_prctl_set(task, ctrl);
761 default: 801 default:
762 return -ENODEV; 802 return -ENODEV;
763 } 803 }
@@ -790,11 +830,34 @@ static int ssb_prctl_get(struct task_struct *task)
790 } 830 }
791} 831}
792 832
833static int ib_prctl_get(struct task_struct *task)
834{
835 if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
836 return PR_SPEC_NOT_AFFECTED;
837
838 switch (spectre_v2_user) {
839 case SPECTRE_V2_USER_NONE:
840 return PR_SPEC_ENABLE;
841 case SPECTRE_V2_USER_PRCTL:
842 if (task_spec_ib_force_disable(task))
843 return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
844 if (task_spec_ib_disable(task))
845 return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
846 return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
847 case SPECTRE_V2_USER_STRICT:
848 return PR_SPEC_DISABLE;
849 default:
850 return PR_SPEC_NOT_AFFECTED;
851 }
852}
853
793int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which) 854int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
794{ 855{
795 switch (which) { 856 switch (which) {
796 case PR_SPEC_STORE_BYPASS: 857 case PR_SPEC_STORE_BYPASS:
797 return ssb_prctl_get(task); 858 return ssb_prctl_get(task);
859 case PR_SPEC_INDIRECT_BRANCH:
860 return ib_prctl_get(task);
798 default: 861 default:
799 return -ENODEV; 862 return -ENODEV;
800 } 863 }
@@ -974,6 +1037,8 @@ static char *stibp_state(void)
974 return ", STIBP: disabled"; 1037 return ", STIBP: disabled";
975 case SPECTRE_V2_USER_STRICT: 1038 case SPECTRE_V2_USER_STRICT:
976 return ", STIBP: forced"; 1039 return ", STIBP: forced";
1040 case SPECTRE_V2_USER_PRCTL:
1041 return "";
977 } 1042 }
978 return ""; 1043 return "";
979} 1044}
@@ -986,6 +1051,8 @@ static char *ibpb_state(void)
986 return ", IBPB: disabled"; 1051 return ", IBPB: disabled";
987 case SPECTRE_V2_USER_STRICT: 1052 case SPECTRE_V2_USER_STRICT:
988 return ", IBPB: always-on"; 1053 return ", IBPB: always-on";
1054 case SPECTRE_V2_USER_PRCTL:
1055 return "";
989 } 1056 }
990 } 1057 }
991 return ""; 1058 return "";
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index afbe2eb4a1c6..7d31192296a8 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -450,6 +450,11 @@ static unsigned long speculation_ctrl_update_tif(struct task_struct *tsk)
450 set_tsk_thread_flag(tsk, TIF_SSBD); 450 set_tsk_thread_flag(tsk, TIF_SSBD);
451 else 451 else
452 clear_tsk_thread_flag(tsk, TIF_SSBD); 452 clear_tsk_thread_flag(tsk, TIF_SSBD);
453
454 if (task_spec_ib_disable(tsk))
455 set_tsk_thread_flag(tsk, TIF_SPEC_IB);
456 else
457 clear_tsk_thread_flag(tsk, TIF_SPEC_IB);
453 } 458 }
454 /* Return the updated threadinfo flags*/ 459 /* Return the updated threadinfo flags*/
455 return task_thread_info(tsk)->flags; 460 return task_thread_info(tsk)->flags;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index a51c13c2b1a0..d607db5fcc6a 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1453,6 +1453,8 @@ static inline bool is_percpu_thread(void)
1453#define PFA_SPREAD_SLAB 2 /* Spread some slab caches over cpuset */ 1453#define PFA_SPREAD_SLAB 2 /* Spread some slab caches over cpuset */
1454#define PFA_SPEC_SSB_DISABLE 3 /* Speculative Store Bypass disabled */ 1454#define PFA_SPEC_SSB_DISABLE 3 /* Speculative Store Bypass disabled */
1455#define PFA_SPEC_SSB_FORCE_DISABLE 4 /* Speculative Store Bypass force disabled*/ 1455#define PFA_SPEC_SSB_FORCE_DISABLE 4 /* Speculative Store Bypass force disabled*/
1456#define PFA_SPEC_IB_DISABLE 5 /* Indirect branch speculation restricted */
1457#define PFA_SPEC_IB_FORCE_DISABLE 6 /* Indirect branch speculation permanently restricted */
1456 1458
1457#define TASK_PFA_TEST(name, func) \ 1459#define TASK_PFA_TEST(name, func) \
1458 static inline bool task_##func(struct task_struct *p) \ 1460 static inline bool task_##func(struct task_struct *p) \
@@ -1484,6 +1486,13 @@ TASK_PFA_CLEAR(SPEC_SSB_DISABLE, spec_ssb_disable)
1484TASK_PFA_TEST(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable) 1486TASK_PFA_TEST(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable)
1485TASK_PFA_SET(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable) 1487TASK_PFA_SET(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable)
1486 1488
1489TASK_PFA_TEST(SPEC_IB_DISABLE, spec_ib_disable)
1490TASK_PFA_SET(SPEC_IB_DISABLE, spec_ib_disable)
1491TASK_PFA_CLEAR(SPEC_IB_DISABLE, spec_ib_disable)
1492
1493TASK_PFA_TEST(SPEC_IB_FORCE_DISABLE, spec_ib_force_disable)
1494TASK_PFA_SET(SPEC_IB_FORCE_DISABLE, spec_ib_force_disable)
1495
1487static inline void 1496static inline void
1488current_restore_flags(unsigned long orig_flags, unsigned long flags) 1497current_restore_flags(unsigned long orig_flags, unsigned long flags)
1489{ 1498{
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index c0d7ea0bf5b6..b17201edfa09 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -212,6 +212,7 @@ struct prctl_mm_map {
212#define PR_SET_SPECULATION_CTRL 53 212#define PR_SET_SPECULATION_CTRL 53
213/* Speculation control variants */ 213/* Speculation control variants */
214# define PR_SPEC_STORE_BYPASS 0 214# define PR_SPEC_STORE_BYPASS 0
215# define PR_SPEC_INDIRECT_BRANCH 1
215/* Return and control values for PR_SET/GET_SPECULATION_CTRL */ 216/* Return and control values for PR_SET/GET_SPECULATION_CTRL */
216# define PR_SPEC_NOT_AFFECTED 0 217# define PR_SPEC_NOT_AFFECTED 0
217# define PR_SPEC_PRCTL (1UL << 0) 218# define PR_SPEC_PRCTL (1UL << 0)
diff --git a/tools/include/uapi/linux/prctl.h b/tools/include/uapi/linux/prctl.h
index c0d7ea0bf5b6..b17201edfa09 100644
--- a/tools/include/uapi/linux/prctl.h
+++ b/tools/include/uapi/linux/prctl.h
@@ -212,6 +212,7 @@ struct prctl_mm_map {
212#define PR_SET_SPECULATION_CTRL 53 212#define PR_SET_SPECULATION_CTRL 53
213/* Speculation control variants */ 213/* Speculation control variants */
214# define PR_SPEC_STORE_BYPASS 0 214# define PR_SPEC_STORE_BYPASS 0
215# define PR_SPEC_INDIRECT_BRANCH 1
215/* Return and control values for PR_SET/GET_SPECULATION_CTRL */ 216/* Return and control values for PR_SET/GET_SPECULATION_CTRL */
216# define PR_SPEC_NOT_AFFECTED 0 217# define PR_SPEC_NOT_AFFECTED 0
217# define PR_SPEC_PRCTL (1UL << 0) 218# define PR_SPEC_PRCTL (1UL << 0)