]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
2fe4128989e05f622f63bb0d25693508e97fc363
[thirdparty/kernel/stable-queue.git] /
1 From 9fa98c9d7b16c30f06d59f4a782052e49db8aec9 Mon Sep 17 00:00:00 2001
2 From: Sasha Levin <sashal@kernel.org>
3 Date: Thu, 5 Nov 2020 16:33:04 +1100
4 Subject: x86/speculation: Allow IBPB to be conditionally enabled on CPUs with
5 always-on STIBP
6
7 From: Anand K Mistry <amistry@google.com>
8
9 [ Upstream commit 1978b3a53a74e3230cd46932b149c6e62e832e9a ]
10
11 On AMD CPUs which have the feature X86_FEATURE_AMD_STIBP_ALWAYS_ON,
12 STIBP is set to on and
13
14 spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED
15
16 At the same time, IBPB can be set to conditional.
17
18 However, this leads to the case where it's impossible to turn on IBPB
19 for a process because in the PR_SPEC_DISABLE case in ib_prctl_set() the
20
21 spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED
22
23 condition leads to a return before the task flag is set. Similarly,
24 ib_prctl_get() will return PR_SPEC_DISABLE even though IBPB is set to
25 conditional.
26
27 More generally, the following cases are possible:
28
29 1. STIBP = conditional && IBPB = on for spectre_v2_user=seccomp,ibpb
30 2. STIBP = on && IBPB = conditional for AMD CPUs with
31 X86_FEATURE_AMD_STIBP_ALWAYS_ON
32
33 The first case functions correctly today, but only because
34 spectre_v2_user_ibpb isn't updated to reflect the IBPB mode.
35
36 At a high level, this change does one thing. If either STIBP or IBPB
37 is set to conditional, allow the prctl to change the task flag.
38 Also, reflect that capability when querying the state. This isn't
39 perfect since it doesn't take into account if only STIBP or IBPB is
40 unconditionally on. But it allows the conditional feature to work as
41 expected, without affecting the unconditional one.
42
43 [ bp: Massage commit message and comment; space out statements for
44 better readability. ]
45
46 Fixes: 21998a351512 ("x86/speculation: Avoid force-disabling IBPB based on STIBP and enhanced IBRS.")
47 Signed-off-by: Anand K Mistry <amistry@google.com>
48 Signed-off-by: Borislav Petkov <bp@suse.de>
49 Acked-by: Thomas Gleixner <tglx@linutronix.de>
50 Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
51 Link: https://lkml.kernel.org/r/20201105163246.v2.1.Ifd7243cd3e2c2206a893ad0a5b9a4f19549e22c6@changeid
52 Signed-off-by: Sasha Levin <sashal@kernel.org>
53 ---
54 arch/x86/kernel/cpu/bugs.c | 51 ++++++++++++++++++++++++--------------
55 1 file changed, 33 insertions(+), 18 deletions(-)
56
57 diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
58 index d3f0db463f96a..581fb7223ad0e 100644
59 --- a/arch/x86/kernel/cpu/bugs.c
60 +++ b/arch/x86/kernel/cpu/bugs.c
61 @@ -1254,6 +1254,14 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
62 return 0;
63 }
64
65 +static bool is_spec_ib_user_controlled(void)
66 +{
67 + return spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL ||
68 + spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP ||
69 + spectre_v2_user_stibp == SPECTRE_V2_USER_PRCTL ||
70 + spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP;
71 +}
72 +
73 static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
74 {
75 switch (ctrl) {
76 @@ -1261,16 +1269,26 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
77 if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
78 spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
79 return 0;
80 +
81 /*
82 - * Indirect branch speculation is always disabled in strict
83 - * mode. It can neither be enabled if it was force-disabled
84 - * by a previous prctl call.
85 + * With strict mode for both IBPB and STIBP, the instruction
86 + * code paths avoid checking this task flag and instead,
87 + * unconditionally run the instruction. However, STIBP and IBPB
88 + * are independent and either can be set to conditionally
89 + * enabled regardless of the mode of the other.
90 + *
91 + * If either is set to conditional, allow the task flag to be
92 + * updated, unless it was force-disabled by a previous prctl
93 + * call. Currently, this is possible on an AMD CPU which has the
94 + * feature X86_FEATURE_AMD_STIBP_ALWAYS_ON. In this case, if the
95 + * kernel is booted with 'spectre_v2_user=seccomp', then
96 + * spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP and
97 + * spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED.
98 */
99 - if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
100 - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
101 - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED ||
102 + if (!is_spec_ib_user_controlled() ||
103 task_spec_ib_force_disable(task))
104 return -EPERM;
105 +
106 task_clear_spec_ib_disable(task);
107 task_update_spec_tif(task);
108 break;
109 @@ -1283,10 +1301,10 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
110 if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
111 spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
112 return -EPERM;
113 - if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
114 - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
115 - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
116 +
117 + if (!is_spec_ib_user_controlled())
118 return 0;
119 +
120 task_set_spec_ib_disable(task);
121 if (ctrl == PR_SPEC_FORCE_DISABLE)
122 task_set_spec_ib_force_disable(task);
123 @@ -1351,20 +1369,17 @@ static int ib_prctl_get(struct task_struct *task)
124 if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
125 spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
126 return PR_SPEC_ENABLE;
127 - else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
128 - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
129 - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
130 - return PR_SPEC_DISABLE;
131 - else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL ||
132 - spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP ||
133 - spectre_v2_user_stibp == SPECTRE_V2_USER_PRCTL ||
134 - spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP) {
135 + else if (is_spec_ib_user_controlled()) {
136 if (task_spec_ib_force_disable(task))
137 return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
138 if (task_spec_ib_disable(task))
139 return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
140 return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
141 - } else
142 + } else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
143 + spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
144 + spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
145 + return PR_SPEC_DISABLE;
146 + else
147 return PR_SPEC_NOT_AFFECTED;
148 }
149
150 --
151 2.27.0
152