Skip to content

Commit ec9404e

Browse files
pa1guptaKAGA-KOKO
authored andcommitted
x86/bhi: Add BHI mitigation knob
Branch history clearing software sequences and hardware control BHI_DIS_S were defined to mitigate Branch History Injection (BHI). Add cmdline spectre_bhi={on|off|auto} to control BHI mitigation: auto - Deploy the hardware mitigation BHI_DIS_S, if available. on - Deploy the hardware mitigation BHI_DIS_S, if available, otherwise deploy the software sequence at syscall entry and VMexit. off - Turn off BHI mitigation. The default is auto mode which does not deploy the software sequence mitigation. This is because of the hardening done in the syscall dispatch path, which is the likely target of BHI. Signed-off-by: Pawan Gupta <[email protected]> Signed-off-by: Daniel Sneddon <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Alexandre Chartre <[email protected]> Reviewed-by: Josh Poimboeuf <[email protected]>
1 parent be482ff commit ec9404e

File tree

5 files changed

+165
-7
lines changed

5 files changed

+165
-7
lines changed

Documentation/admin-guide/hw-vuln/spectre.rst

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,10 @@ associated with the source address of the indirect branch. Specifically,
138138
the BHB might be shared across privilege levels even in the presence of
139139
Enhanced IBRS.
140140

141-
Currently the only known real-world BHB attack vector is via
142-
unprivileged eBPF. Therefore, it's highly recommended to not enable
143-
unprivileged eBPF, especially when eIBRS is used (without retpolines).
144-
For a full mitigation against BHB attacks, it's recommended to use
145-
retpolines (or eIBRS combined with retpolines).
141+
Previously the only known real-world BHB attack vector was via unprivileged
142+
eBPF. Further research has found attacks that don't require unprivileged eBPF.
143+
For a full mitigation against BHB attacks it is recommended to set BHI_DIS_S or
144+
use the BHB clearing sequence.
146145

147146
Attack scenarios
148147
----------------
@@ -430,6 +429,21 @@ The possible values in this file are:
430429
'PBRSB-eIBRS: Not affected' CPU is not affected by PBRSB
431430
=========================== =======================================================
432431

432+
- Branch History Injection (BHI) protection status:
433+
434+
.. list-table::
435+
436+
* - BHI: Not affected
437+
- System is not affected
438+
* - BHI: Retpoline
439+
- System is protected by retpoline
440+
* - BHI: BHI_DIS_S
441+
- System is protected by BHI_DIS_S
442+
* - BHI: SW loop
443+
- System is protected by software clearing sequence
444+
* - BHI: Syscall hardening
445+
- Syscalls are hardened against BHI
446+
433447
Full mitigation might require a microcode update from the CPU
434448
vendor. When the necessary microcode is not available, the kernel will
435449
report vulnerability.
@@ -484,7 +498,11 @@ Spectre variant 2
484498

485499
Systems which support enhanced IBRS (eIBRS) enable IBRS protection once at
486500
boot, by setting the IBRS bit, and they're automatically protected against
487-
Spectre v2 variant attacks.
501+
some Spectre v2 variant attacks. The BHB can still influence the choice of
502+
indirect branch predictor entry, and although branch predictor entries are
503+
isolated between modes when eIBRS is enabled, the BHB itself is not isolated
504+
between modes. Systems which support BHI_DIS_S will set it to protect against
505+
BHI attacks.
488506

489507
On Intel's enhanced IBRS systems, this includes cross-thread branch target
490508
injections on SMT systems (STIBP). In other words, Intel eIBRS enables
@@ -638,6 +656,21 @@ kernel command line.
638656
spectre_v2=off. Spectre variant 1 mitigations
639657
cannot be disabled.
640658

659+
spectre_bhi=
660+
661+
[X86] Control mitigation of Branch History Injection
662+
(BHI) vulnerability. Syscalls are hardened against BHI
663+
regardless of this setting. This setting affects the deployment
664+
of the HW BHI control and the SW BHB clearing sequence.
665+
666+
on
667+
unconditionally enable.
668+
off
669+
unconditionally disable.
670+
auto
671+
enable if hardware mitigation
672+
control(BHI_DIS_S) is available.
673+
641674
For spectre_v2_user see Documentation/admin-guide/kernel-parameters.txt
642675

643676
Mitigation selection guide

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6063,6 +6063,17 @@
60636063
sonypi.*= [HW] Sony Programmable I/O Control Device driver
60646064
See Documentation/admin-guide/laptops/sonypi.rst
60656065

6066+
spectre_bhi= [X86] Control mitigation of Branch History Injection
6067+
(BHI) vulnerability. Syscalls are hardened against BHI
6068+
reglardless of this setting. This setting affects the
6069+
deployment of the HW BHI control and the SW BHB
6070+
clearing sequence.
6071+
6072+
on - unconditionally enable.
6073+
off - unconditionally disable.
6074+
auto - (default) enable only if hardware mitigation
6075+
control(BHI_DIS_S) is available.
6076+
60666077
spectre_v2= [X86,EARLY] Control mitigation of Spectre variant 2
60676078
(indirect branch speculation) vulnerability.
60686079
The default operation protects the kernel from

arch/x86/Kconfig

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2633,6 +2633,31 @@ config MITIGATION_RFDS
26332633
stored in floating point, vector and integer registers.
26342634
See also <file:Documentation/admin-guide/hw-vuln/reg-file-data-sampling.rst>
26352635

2636+
choice
2637+
prompt "Clear branch history"
2638+
depends on CPU_SUP_INTEL
2639+
default SPECTRE_BHI_AUTO
2640+
help
2641+
Enable BHI mitigations. BHI attacks are a form of Spectre V2 attacks
2642+
where the branch history buffer is poisoned to speculatively steer
2643+
indirect branches.
2644+
See <file:Documentation/admin-guide/hw-vuln/spectre.rst>
2645+
2646+
config SPECTRE_BHI_ON
2647+
bool "on"
2648+
help
2649+
Equivalent to setting spectre_bhi=on command line parameter.
2650+
config SPECTRE_BHI_OFF
2651+
bool "off"
2652+
help
2653+
Equivalent to setting spectre_bhi=off command line parameter.
2654+
config SPECTRE_BHI_AUTO
2655+
bool "auto"
2656+
help
2657+
Equivalent to setting spectre_bhi=auto command line parameter.
2658+
2659+
endchoice
2660+
26362661
endif
26372662

26382663
config ARCH_HAS_ADD_PAGES

arch/x86/include/asm/cpufeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@
468468
#define X86_FEATURE_AMD_LBR_PMC_FREEZE (21*32+ 0) /* AMD LBR and PMC Freeze */
469469
#define X86_FEATURE_CLEAR_BHB_LOOP (21*32+ 1) /* "" Clear branch history at syscall entry using SW loop */
470470
#define X86_FEATURE_BHI_CTRL (21*32+ 2) /* "" BHI_DIS_S HW control available */
471+
#define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* "" BHI_DIS_S HW control enabled */
471472

472473
/*
473474
* BUG word(s)

arch/x86/kernel/cpu/bugs.c

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1607,6 +1607,74 @@ static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_
16071607
dump_stack();
16081608
}
16091609

1610+
/*
1611+
* Set BHI_DIS_S to prevent indirect branches in kernel to be influenced by
1612+
* branch history in userspace. Not needed if BHI_NO is set.
1613+
*/
1614+
static bool __init spec_ctrl_bhi_dis(void)
1615+
{
1616+
if (!boot_cpu_has(X86_FEATURE_BHI_CTRL))
1617+
return false;
1618+
1619+
x86_spec_ctrl_base |= SPEC_CTRL_BHI_DIS_S;
1620+
update_spec_ctrl(x86_spec_ctrl_base);
1621+
setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_HW);
1622+
1623+
return true;
1624+
}
1625+
1626+
enum bhi_mitigations {
1627+
BHI_MITIGATION_OFF,
1628+
BHI_MITIGATION_ON,
1629+
BHI_MITIGATION_AUTO,
1630+
};
1631+
1632+
static enum bhi_mitigations bhi_mitigation __ro_after_init =
1633+
IS_ENABLED(CONFIG_SPECTRE_BHI_ON) ? BHI_MITIGATION_ON :
1634+
IS_ENABLED(CONFIG_SPECTRE_BHI_OFF) ? BHI_MITIGATION_OFF :
1635+
BHI_MITIGATION_AUTO;
1636+
1637+
static int __init spectre_bhi_parse_cmdline(char *str)
1638+
{
1639+
if (!str)
1640+
return -EINVAL;
1641+
1642+
if (!strcmp(str, "off"))
1643+
bhi_mitigation = BHI_MITIGATION_OFF;
1644+
else if (!strcmp(str, "on"))
1645+
bhi_mitigation = BHI_MITIGATION_ON;
1646+
else if (!strcmp(str, "auto"))
1647+
bhi_mitigation = BHI_MITIGATION_AUTO;
1648+
else
1649+
pr_err("Ignoring unknown spectre_bhi option (%s)", str);
1650+
1651+
return 0;
1652+
}
1653+
early_param("spectre_bhi", spectre_bhi_parse_cmdline);
1654+
1655+
static void __init bhi_select_mitigation(void)
1656+
{
1657+
if (bhi_mitigation == BHI_MITIGATION_OFF)
1658+
return;
1659+
1660+
/* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */
1661+
if (cpu_feature_enabled(X86_FEATURE_RETPOLINE) &&
1662+
!(x86_read_arch_cap_msr() & ARCH_CAP_RRSBA))
1663+
return;
1664+
1665+
if (spec_ctrl_bhi_dis())
1666+
return;
1667+
1668+
if (!IS_ENABLED(CONFIG_X86_64))
1669+
return;
1670+
1671+
if (bhi_mitigation == BHI_MITIGATION_AUTO)
1672+
return;
1673+
1674+
setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP);
1675+
pr_info("Spectre BHI mitigation: SW BHB clearing on syscall\n");
1676+
}
1677+
16101678
static void __init spectre_v2_select_mitigation(void)
16111679
{
16121680
enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
@@ -1718,6 +1786,9 @@ static void __init spectre_v2_select_mitigation(void)
17181786
mode == SPECTRE_V2_RETPOLINE)
17191787
spec_ctrl_disable_kernel_rrsba();
17201788

1789+
if (boot_cpu_has(X86_BUG_BHI))
1790+
bhi_select_mitigation();
1791+
17211792
spectre_v2_enabled = mode;
17221793
pr_info("%s\n", spectre_v2_strings[mode]);
17231794

@@ -2733,6 +2804,21 @@ static char *pbrsb_eibrs_state(void)
27332804
}
27342805
}
27352806

2807+
static const char * const spectre_bhi_state(void)
2808+
{
2809+
if (!boot_cpu_has_bug(X86_BUG_BHI))
2810+
return "; BHI: Not affected";
2811+
else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW))
2812+
return "; BHI: BHI_DIS_S";
2813+
else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP))
2814+
return "; BHI: SW loop";
2815+
else if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
2816+
!(x86_read_arch_cap_msr() & ARCH_CAP_RRSBA))
2817+
return "; BHI: Retpoline";
2818+
2819+
return "; BHI: Vulnerable (Syscall hardening enabled)";
2820+
}
2821+
27362822
static ssize_t spectre_v2_show_state(char *buf)
27372823
{
27382824
if (spectre_v2_enabled == SPECTRE_V2_LFENCE)
@@ -2745,13 +2831,15 @@ static ssize_t spectre_v2_show_state(char *buf)
27452831
spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE)
27462832
return sysfs_emit(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n");
27472833

2748-
return sysfs_emit(buf, "%s%s%s%s%s%s%s\n",
2834+
return sysfs_emit(buf, "%s%s%s%s%s%s%s%s\n",
27492835
spectre_v2_strings[spectre_v2_enabled],
27502836
ibpb_state(),
27512837
boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? "; IBRS_FW" : "",
27522838
stibp_state(),
27532839
boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? "; RSB filling" : "",
27542840
pbrsb_eibrs_state(),
2841+
spectre_bhi_state(),
2842+
/* this should always be at the end */
27552843
spectre_v2_module_string());
27562844
}
27572845

0 commit comments

Comments
 (0)