Skip to content

Commit 1978b3a

Browse files
akmistrysuryasaimadhu
authored andcommitted
x86/speculation: Allow IBPB to be conditionally enabled on CPUs with always-on STIBP
On AMD CPUs which have the feature X86_FEATURE_AMD_STIBP_ALWAYS_ON, STIBP is set to on and spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED At the same time, IBPB can be set to conditional. However, this leads to the case where it's impossible to turn on IBPB for a process because in the PR_SPEC_DISABLE case in ib_prctl_set() the spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED condition leads to a return before the task flag is set. Similarly, ib_prctl_get() will return PR_SPEC_DISABLE even though IBPB is set to conditional. More generally, the following cases are possible: 1. STIBP = conditional && IBPB = on for spectre_v2_user=seccomp,ibpb 2. STIBP = on && IBPB = conditional for AMD CPUs with X86_FEATURE_AMD_STIBP_ALWAYS_ON The first case functions correctly today, but only because spectre_v2_user_ibpb isn't updated to reflect the IBPB mode. At a high level, this change does one thing. If either STIBP or IBPB is set to conditional, allow the prctl to change the task flag. Also, reflect that capability when querying the state. This isn't perfect since it doesn't take into account if only STIBP or IBPB is unconditionally on. But it allows the conditional feature to work as expected, without affecting the unconditional one. [ bp: Massage commit message and comment; space out statements for better readability. ] Fixes: 21998a3 ("x86/speculation: Avoid force-disabling IBPB based on STIBP and enhanced IBRS.") Signed-off-by: Anand K Mistry <amistry@google.com> Signed-off-by: Borislav Petkov <bp@suse.de> Acked-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Tom Lendacky <thomas.lendacky@amd.com> Link: https://lkml.kernel.org/r/20201105163246.v2.1.Ifd7243cd3e2c2206a893ad0a5b9a4f19549e22c6@changeid
1 parent 4d6ffa2 commit 1978b3a

1 file changed

Lines changed: 33 additions & 18 deletions

File tree

arch/x86/kernel/cpu/bugs.c

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,23 +1254,41 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
12541254
return 0;
12551255
}
12561256

1257+
static bool is_spec_ib_user_controlled(void)
1258+
{
1259+
return spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL ||
1260+
spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP ||
1261+
spectre_v2_user_stibp == SPECTRE_V2_USER_PRCTL ||
1262+
spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP;
1263+
}
1264+
12571265
static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
12581266
{
12591267
switch (ctrl) {
12601268
case PR_SPEC_ENABLE:
12611269
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
12621270
spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
12631271
return 0;
1272+
12641273
/*
1265-
* Indirect branch speculation is always disabled in strict
1266-
* mode. It can neither be enabled if it was force-disabled
1267-
* by a previous prctl call.
1274+
* With strict mode for both IBPB and STIBP, the instruction
1275+
* code paths avoid checking this task flag and instead,
1276+
* unconditionally run the instruction. However, STIBP and IBPB
1277+
* are independent and either can be set to conditionally
1278+
* enabled regardless of the mode of the other.
1279+
*
1280+
* If either is set to conditional, allow the task flag to be
1281+
* updated, unless it was force-disabled by a previous prctl
1282+
* call. Currently, this is possible on an AMD CPU which has the
1283+
* feature X86_FEATURE_AMD_STIBP_ALWAYS_ON. In this case, if the
1284+
* kernel is booted with 'spectre_v2_user=seccomp', then
1285+
* spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP and
1286+
* spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED.
12681287
*/
1269-
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
1270-
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
1271-
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED ||
1288+
if (!is_spec_ib_user_controlled() ||
12721289
task_spec_ib_force_disable(task))
12731290
return -EPERM;
1291+
12741292
task_clear_spec_ib_disable(task);
12751293
task_update_spec_tif(task);
12761294
break;
@@ -1283,10 +1301,10 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
12831301
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
12841302
spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
12851303
return -EPERM;
1286-
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
1287-
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
1288-
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
1304+
1305+
if (!is_spec_ib_user_controlled())
12891306
return 0;
1307+
12901308
task_set_spec_ib_disable(task);
12911309
if (ctrl == PR_SPEC_FORCE_DISABLE)
12921310
task_set_spec_ib_force_disable(task);
@@ -1351,20 +1369,17 @@ static int ib_prctl_get(struct task_struct *task)
13511369
if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
13521370
spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
13531371
return PR_SPEC_ENABLE;
1354-
else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
1355-
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
1356-
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
1357-
return PR_SPEC_DISABLE;
1358-
else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL ||
1359-
spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP ||
1360-
spectre_v2_user_stibp == SPECTRE_V2_USER_PRCTL ||
1361-
spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP) {
1372+
else if (is_spec_ib_user_controlled()) {
13621373
if (task_spec_ib_force_disable(task))
13631374
return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
13641375
if (task_spec_ib_disable(task))
13651376
return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
13661377
return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
1367-
} else
1378+
} else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
1379+
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
1380+
spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
1381+
return PR_SPEC_DISABLE;
1382+
else
13681383
return PR_SPEC_NOT_AFFECTED;
13691384
}
13701385

0 commit comments

Comments
 (0)