From: Breno Leitao <[email protected]>
Create an entry for each CPU mitigation under
CONFIG_SPECULATION_MITIGATIONS. This allow users to enable or disable
them at compilation time.
If a mitigation is disabled at compilation time, it could be enabled at
runtime using kernel command line arguments.
Signed-off-by: Breno Leitao <[email protected]>
---
V1:
* Creates a way to mitigate all (or none) hardware bugs
V2:
* Create KCONFIGs entries only some hardware bugs (MDS, TAA, MMIO)
V3:
* Expand the mitigations KCONFIGs to all hardware bugs that are
Linux mitigates.
---
arch/x86/Kconfig | 93 ++++++++++++++++++++++++++++++++++++++
arch/x86/kernel/cpu/bugs.c | 50 +++++++++++++++++---
2 files changed, 137 insertions(+), 6 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 53bab123a8ee..53a751927a57 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2649,6 +2649,99 @@ config SLS
against straight line speculation. The kernel image might be slightly
larger.
+config MITIGATE_MDS
+ bool "Mitigate Microarchitectural Data Sampling (MDS) hardware bug"
+ depends on CPU_SUP_INTEL
+ default y
+ help
+ Enable mitigation for Microarchitectural Data Sampling (MDS). MDS is
+ a hardware vulnerability which allows unprivileged speculative access
+ to data which is available in various CPU internal buffer. Deeper
+ technical information is available in the MDS specific x86 architecture
+ section: Documentation/arch/x86/mds.rst.
+
+config MITIGATE_TAA
+ bool "Mitigate TSX Asynchronous Abort (TAA) hardware bug"
+ depends on CPU_SUP_INTEL
+ default y
+ help
+ Enable mitigation for TSX Asynchronous Abort (TAA). TAA is a hardware
+ vulnerability that allows unprivileged speculative access to data
+ which is available in various CPU internal buffers by using
+ asynchronous aborts within an Intel TSX transactional region.
+
+config MITIGATE_MMIO_STALE_DATA
+ bool "Mitigate MMIO Stale Data hardware bug"
+ depends on CPU_SUP_INTEL
+ default y
+ help
+ Enable mitigation for MMIO Stale Data hardware bugs. Processor MMIO
+ Stale Data Vulnerabilities are a class of memory-mapped I/O (MMIO)
+ vulnerabilities that can expose data. The vulnerabilities require the
+ attacker to have access to MMIO.
+
+config MITIGATE_L1TF
+ bool "Mitigate L1 Terminal Fault (L1TF) hardware bug"
+ default y
+ help
+ Mitigate L1 Terminal Fault (L1TF) hardware bug. L1 Terminal Fault is a
+ hardware vulnerability which allows unprivileged speculative access to data
+ which is available in the Level 1 Data Cache when the page table
+ entry controlling the virtual address.
+
+config MITIGATE_RETBLEED
+ bool "Mitigate RETBleed hardware bug"
+ default y
+ help
+ Enable mitigation for RETBleed (Arbitrary Speculative Code Execution
+ with Return Instructions) vulnerability. RETBleed is a speculative
+ execution attack which takes advantage of microarchitectural behavior
+ in many modern microprocessors, similar to Spectre v2. An
+ unprivileged attacker can use these flaws to bypass conventional
+ memory security restrictions to gain read access to privileged memory
+ that would otherwise be inaccessible.
+
+config MITIGATE_SPECTRE_V1
+ bool "Mitigate SPECTRE V1 hardware bug"
+ default y
+ help
+ Enable mitigation for Spectre V1 (Bounds Check Bypass). Spectre V1 is a
+ class of side channel attacks that takes advantage of speculative
+ execution that bypasses conditional branch instructions used for
+ memory access bounds check.
+
+config MITIGATE_SPECTRE_V2
+ bool "Mitigate SPECTRE V2 hardware bug"
+ default y
+ help
+ Enable mitigation for Spectre V2 (Branch Target Injection). Spectre
+ V2 is a class of side channel attacks that takes advantage of
+ indirect branch predictors inside the processor. In Spectre variant 2
+ attacks, the attacker can steer speculative indirect branches in the
+ victim to gadget code by poisoning the branch target buffer of a CPU
+ used for predicting indirect branch addresses.
+
+config MITIGATE_SRBDS
+ bool "Mitigate Special Register Buffer Data Sampling (SRBDS) hardware bug"
+ depends on CPU_SUP_INTEL
+ default y
+ help
+ Enable mitigation for Special Register Buffer Data Sampling (SRBDS).
+ SRBDS is a hardware vulnerability that allows Microarchitectural Data
+ Sampling (MDS) techniques to infer values returned from special
+ register accesses. An unprivileged user can extract values returned
+ from RDRAND and RDSEED executed on another core or sibling thread
+ using MDS techniques.
+
+config MITIGATE_SSB
+ bool "Mitigate Speculative Store Bypass (SSB) hardware bug"
+ default y
+ help
+ Enable mitigation for Speculative Store Bypass (SSB). SSB is a
+ hardware security vulnerability and its exploitation takes advantage
+ of speculative execution in a similar way to the Meltdown and Spectre
+ security vulnerabilities.
+
endif
config ARCH_HAS_ADD_PAGES
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 182af64387d0..c351eed75a14 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -267,7 +267,11 @@ static void x86_amd_ssb_disable(void)
#define pr_fmt(fmt) "MDS: " fmt
/* Default mitigation for MDS-affected CPUs */
+#if IS_ENABLED(CONFIG_MITIGATE_MDS)
static enum mds_mitigations mds_mitigation __ro_after_init = MDS_MITIGATION_FULL;
+#else
+static enum mds_mitigations mds_mitigation __ro_after_init = MDS_MITIGATION_OFF;
+#endif
static bool mds_nosmt __ro_after_init = false;
static const char * const mds_strings[] = {
@@ -327,7 +331,11 @@ enum taa_mitigations {
};
/* Default mitigation for TAA-affected CPUs */
+#if IS_ENABLED(CONFIG_MITIGATE_TAA)
static enum taa_mitigations taa_mitigation __ro_after_init = TAA_MITIGATION_VERW;
+#else
+static enum taa_mitigations taa_mitigation __ro_after_init = TAA_MITIGATION_OFF;
+#endif
static bool taa_nosmt __ro_after_init;
static const char * const taa_strings[] = {
@@ -428,7 +436,11 @@ enum mmio_mitigations {
};
/* Default mitigation for Processor MMIO Stale Data vulnerabilities */
+#if IS_ENABLED(CONFIG_MITIGATE_MMIO_STALE_DATA)
static enum mmio_mitigations mmio_mitigation __ro_after_init = MMIO_MITIGATION_VERW;
+#else
+static enum mmio_mitigations mmio_mitigation __ro_after_init = MMIO_MITIGATION_OFF;
+#endif
static bool mmio_nosmt __ro_after_init = false;
static const char * const mmio_strings[] = {
@@ -577,7 +589,11 @@ enum srbds_mitigations {
SRBDS_MITIGATION_HYPERVISOR,
};
+#if IS_ENABLED(CONFIG_MITIGATE_SRBDS)
static enum srbds_mitigations srbds_mitigation __ro_after_init = SRBDS_MITIGATION_FULL;
+#else
+static enum srbds_mitigations srbds_mitigation __ro_after_init = SRBDS_MITIGATION_OFF;
+#endif
static const char * const srbds_strings[] = {
[SRBDS_MITIGATION_OFF] = "Vulnerable",
@@ -702,8 +718,13 @@ enum spectre_v1_mitigation {
SPECTRE_V1_MITIGATION_AUTO,
};
+#if IS_ENABLED(CONFIG_MITIGATE_SPECTRE_V1)
static enum spectre_v1_mitigation spectre_v1_mitigation __ro_after_init =
SPECTRE_V1_MITIGATION_AUTO;
+#else
+static enum spectre_v1_mitigation spectre_v1_mitigation __ro_after_init =
+ SPECTRE_V1_MITIGATION_NONE;
+#endif
static const char * const spectre_v1_strings[] = {
[SPECTRE_V1_MITIGATION_NONE] = "Vulnerable: __user pointer sanitization and usercopy barriers only; no swapgs barriers",
@@ -817,8 +838,13 @@ static const char * const retbleed_strings[] = {
static enum retbleed_mitigation retbleed_mitigation __ro_after_init =
RETBLEED_MITIGATION_NONE;
+#if IS_ENABLED(CONFIG_MITIGATE_RETBLEED)
static enum retbleed_mitigation_cmd retbleed_cmd __ro_after_init =
RETBLEED_CMD_AUTO;
+#else
+static enum retbleed_mitigation_cmd retbleed_cmd __ro_after_init =
+ RETBLEED_CMD_OFF;
+#endif
static int __ro_after_init retbleed_nosmt = false;
@@ -1273,7 +1299,11 @@ static void __init spec_v2_print_cond(const char *reason, bool secure)
static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
{
+#if IS_ENABLED(CONFIG_MITIGATE_SPECTRE_V2)
enum spectre_v2_mitigation_cmd cmd = SPECTRE_V2_CMD_AUTO;
+#else
+ enum spectre_v2_mitigation_cmd cmd = SPECTRE_V2_CMD_NONE;
+#endif
char arg[20];
int ret, i;
@@ -1283,7 +1313,7 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg));
if (ret < 0)
- return SPECTRE_V2_CMD_AUTO;
+ return cmd;
for (i = 0; i < ARRAY_SIZE(mitigation_options); i++) {
if (!match_option(arg, ret, mitigation_options[i].option))
@@ -1293,8 +1323,8 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
}
if (i >= ARRAY_SIZE(mitigation_options)) {
- pr_err("unknown option (%s). Switching to AUTO select\n", arg);
- return SPECTRE_V2_CMD_AUTO;
+ pr_err("unknown option (%s). Switching to default mode\n", arg);
+ return cmd;
}
if ((cmd == SPECTRE_V2_CMD_RETPOLINE ||
@@ -1767,7 +1797,11 @@ static const struct {
static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void)
{
+#if IS_ENABLED(CONFIG_MITIGATE_SSB)
enum ssb_mitigation_cmd cmd = SPEC_STORE_BYPASS_CMD_AUTO;
+#else
+ enum ssb_mitigation_cmd cmd = SPEC_STORE_BYPASS_CMD_NONE;
+#endif
char arg[20];
int ret, i;
@@ -1778,7 +1812,7 @@ static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void)
ret = cmdline_find_option(boot_command_line, "spec_store_bypass_disable",
arg, sizeof(arg));
if (ret < 0)
- return SPEC_STORE_BYPASS_CMD_AUTO;
+ return cmd;
for (i = 0; i < ARRAY_SIZE(ssb_mitigation_options); i++) {
if (!match_option(arg, ret, ssb_mitigation_options[i].option))
@@ -1789,8 +1823,8 @@ static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void)
}
if (i >= ARRAY_SIZE(ssb_mitigation_options)) {
- pr_err("unknown option (%s). Switching to AUTO select\n", arg);
- return SPEC_STORE_BYPASS_CMD_AUTO;
+ pr_err("unknown option (%s). Switching to default mode\n", arg);
+ return cmd;
}
}
@@ -2116,7 +2150,11 @@ EXPORT_SYMBOL_GPL(itlb_multihit_kvm_mitigation);
#define pr_fmt(fmt) "L1TF: " fmt
/* Default mitigation for L1TF-affected CPUs */
+#if IS_ENABLED(CONFIG_MITIGATE_L1TF)
enum l1tf_mitigations l1tf_mitigation __ro_after_init = L1TF_MITIGATION_FLUSH;
+#else
+enum l1tf_mitigations l1tf_mitigation __ro_after_init = L1TF_MITIGATION_OFF;
+#endif
#if IS_ENABLED(CONFIG_KVM_INTEL)
EXPORT_SYMBOL_GPL(l1tf_mitigation);
#endif
--
2.34.1
On Wed, Jun 28, 2023 at 07:21:28AM -0700, [email protected] wrote:
> From: Breno Leitao <[email protected]>
>
> Create an entry for each CPU mitigation under
> CONFIG_SPECULATION_MITIGATIONS. This allow users to enable or disable
> them at compilation time.
>
> If a mitigation is disabled at compilation time, it could be enabled at
> runtime using kernel command line arguments.
I had a chat about this topic with Boris and Thomas at Kernel Recipes,
and I would like to summarize the current state, and get it moving
forward.
1) The hardware mitigations are half-way added to KCONFIG. I.e., half of
the hardware mitigations are specified under SPECULATION_MITIGATIONS,
but not all of them.
* You can enabled/disabled just half of them at build time.
2) It is impossible to build a kernel with speculative mitigations
disabled.
* The only way to disable the mitigations is at boot time,
using the "mitigations=off" boot parameter.
So, disabling SPECULATION_MITIGATIONS, will only disable the mitigations
that are under SPECULATION_MITIGATIONS. Other mitigations will continue
to be enabled by default. This is is misleading for the user.
Here are a few options moving forward:
1) Create one Kconfig entry per mitigation, so, the user can pick and
choose what to enable and disable. (Version 3 of this patch. May need a
re-spin due to the new mitigations being added.)
2) Keep the Kconfig entries as-is. Create a new Kconfig entry
(CPU_MITIGATIONS_DEFAULT_OFF?) to disable the mitigations by default,
similarly to the `mitigations=off` boot parameter (v1 of this patch)
3) Same as 2, but, reusing SPECULATION_MITIGATIONS instead of
creating a new Kconfig entry.
4) Remove the current entries in SPECULATION_MITIGATIONS and the fine
control on what to enable/disable?!
What is the preferred way?
On Thu, Sep 28, 2023 at 06:40:18AM -0700, Dave Hansen wrote:
> On 9/28/23 05:45, Breno Leitao wrote:
> > 1) Create one Kconfig entry per mitigation, so, the user can pick and
> > choose what to enable and disable. (Version 3 of this patch. May need a
> > re-spin due to the new mitigations being added.)
>
> This means, what, roughly 18 today?
>
> #define X86_BUG_CPU_MELTDOWN X86_BUG(14)
> ...
> #define X86_BUG_GDS X86_BUG(30)
>
> Plus two bonus ones:
>
> #define X86_BUG_SRSO X86_BUG(1*32 + 0)
> #define X86_BUG_DIV0 X86_BUG(1*32 + 1)
>
> ... and we've slowed down the rate at which we're adding these, but
> we're still seeing a couple a year.
>
> Perhaps Pawan and the others actually _doing_ the patches for these can
> speak up, but I don't think adding a Kconfig option will be too much
> additional work for each new X86_BUG.
>
> I still think it's highly unlikely that someone will come through and
> pick and choose among a few dozen vulnerabilities.
That is what my experience tells me as well. You either have a insecure
and fast kernel, or a hardened one. In some big companies, you can have
both, and choose which one you want to boot depending on the workload.
On Thu, Sep 28, 2023 at 06:40:18AM -0700, Dave Hansen wrote:
> On 9/28/23 05:45, Breno Leitao wrote:
> > 1) Create one Kconfig entry per mitigation, so, the user can pick and
> > choose what to enable and disable. (Version 3 of this patch. May need a
> > re-spin due to the new mitigations being added.)
>
> This means, what, roughly 18 today?
>
> #define X86_BUG_CPU_MELTDOWN X86_BUG(14)
> ...
> #define X86_BUG_GDS X86_BUG(30)
>
> Plus two bonus ones:
>
> #define X86_BUG_SRSO X86_BUG(1*32 + 0)
> #define X86_BUG_DIV0 X86_BUG(1*32 + 1)
>
> ... and we've slowed down the rate at which we're adding these, but
> we're still seeing a couple a year.
>
> Perhaps Pawan and the others actually _doing_ the patches for these can
> speak up, but I don't think adding a Kconfig option will be too much
> additional work for each new X86_BUG.
It is trivial, but seems unnecessary IMO.
> I still think it's highly unlikely that someone will come through and
> pick and choose among a few dozen vulnerabilities.
Second that.
If we do want to provide more control, personally I would like:
- Global control for all mitigations
- Enable only cheap mitigations
This could enable mitigations as long as it doesn't hurt the performance
too badly. The challenge being whether a mitigation is cheap or costly
is subjective and highly depends on workloads. Without a standard way of
categorizing a mitigation it will be hard to reach a consensus. OTOH,
there are mitigations that are relatively cheaper e.g. Enhanced IBRS.
Other way to categorize could be:
- Global control for all mitigations
- Guest only mitigations (host userspace is trusted)
This control can disable all mitigation for userspace, but will continue
to mitigate host against a rouge guests. This could be quite a lot of
work.
On 9/28/23 05:45, Breno Leitao wrote:
> 1) Create one Kconfig entry per mitigation, so, the user can pick and
> choose what to enable and disable. (Version 3 of this patch. May need a
> re-spin due to the new mitigations being added.)
This means, what, roughly 18 today?
#define X86_BUG_CPU_MELTDOWN X86_BUG(14)
...
#define X86_BUG_GDS X86_BUG(30)
Plus two bonus ones:
#define X86_BUG_SRSO X86_BUG(1*32 + 0)
#define X86_BUG_DIV0 X86_BUG(1*32 + 1)
... and we've slowed down the rate at which we're adding these, but
we're still seeing a couple a year.
Perhaps Pawan and the others actually _doing_ the patches for these can
speak up, but I don't think adding a Kconfig option will be too much
additional work for each new X86_BUG.
I still think it's highly unlikely that someone will come through and
pick and choose among a few dozen vulnerabilities.
+ Linus.
On Thu, Sep 28, 2023 at 05:45:32AM -0700, Breno Leitao wrote:
> On Wed, Jun 28, 2023 at 07:21:28AM -0700, [email protected] wrote:
> > From: Breno Leitao <[email protected]>
> >
> > Create an entry for each CPU mitigation under
> > CONFIG_SPECULATION_MITIGATIONS. This allow users to enable or disable
> > them at compilation time.
> >
> > If a mitigation is disabled at compilation time, it could be enabled at
> > runtime using kernel command line arguments.
>
> I had a chat about this topic with Boris and Thomas at Kernel Recipes,
> and I would like to summarize the current state, and get it moving
> forward.
>
> 1) The hardware mitigations are half-way added to KCONFIG. I.e., half of
> the hardware mitigations are specified under SPECULATION_MITIGATIONS,
> but not all of them.
> * You can enabled/disabled just half of them at build time.
>
> 2) It is impossible to build a kernel with speculative mitigations
> disabled.
> * The only way to disable the mitigations is at boot time,
> using the "mitigations=off" boot parameter.
>
>
> So, disabling SPECULATION_MITIGATIONS, will only disable the mitigations
> that are under SPECULATION_MITIGATIONS. Other mitigations will continue
> to be enabled by default. This is is misleading for the user.
>
> Here are a few options moving forward:
>
> 1) Create one Kconfig entry per mitigation, so, the user can pick and
> choose what to enable and disable. (Version 3 of this patch. May need a
> re-spin due to the new mitigations being added.)
>
> 2) Keep the Kconfig entries as-is. Create a new Kconfig entry
> (CPU_MITIGATIONS_DEFAULT_OFF?) to disable the mitigations by default,
> similarly to the `mitigations=off` boot parameter (v1 of this patch)
>
> 3) Same as 2, but, reusing SPECULATION_MITIGATIONS instead of
> creating a new Kconfig entry.
>
> 4) Remove the current entries in SPECULATION_MITIGATIONS and the fine
> control on what to enable/disable?!
>
> What is the preferred way?
I happen to know that Linus wanted those per mitigation, perhaps to be
able to disable only a subset of them.
Linus, what are you thoughts on it, should we continue with a Kconfig
option per mitigation or should we hide them all behind a single Kconfig
option - which would be a lot simpler and easier?
Apparently people want to completely remove the mitigations crap for
some configurations at build time already.
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
On Thu, 5 Oct 2023 at 09:26, Borislav Petkov <[email protected]> wrote:
>
> I happen to know that Linus wanted those per mitigation, perhaps to be
> able to disable only a subset of them.
Partly for that - some of them are more obnoxious than others, and
cause more changes to code generation.
And partly I want separate configs for just source code readability,
so that we see *which* butt-ugly piece of crap code is for what
reason.
> Linus, what are you thoughts on it, should we continue with a Kconfig
> option per mitigation or should we hide them all behind a single Kconfig
> option - which would be a lot simpler and easier?
>
> Apparently people want to completely remove the mitigations crap for
> some configurations at build time already.
I'd be perfectly happy with a top-level Kconfig question for "enable
mitigations", which could be a config with three values ("all", "none"
and "finegrained").
But see above (particularly the second thing) on why I want us to
still have individual config options for each individual issue. I'm
not convinced a lot of people *care* about the "finegrained" case of
enabling/disabling each mitigation at build time), but I do use it
myself because some of the mitigations end up changing code generation
*so* much that it gets hard to even read the generated assembly (ie
all the retpoline crap looks *horrendous* if what you actually want to
do is check that some change helps code generation and want to
actually look at the resulting *.s files).
Same goes for some perf runs, so this is not *just* "I do a build and
look at the result" - I want to be able to run it too.
So I'll keep the mitigations that don't f*ck up my system too much,
and then because I actually do look at the generated code when I match
up source and result (ie the whole "annotate" thing in perf), things
like retpoline really do end up screwing things up horrendously, in
ways that some of the other mitigations don't.
Maybe I'm odd in the above "disable some mitigations to see the code
generation", but the source-level "readability", and the "this crazy
code is because of this mitigation" is still important, I feel.
I do *not* want to live in a world where we have random crazy code and
just a "#ifdef CONFIG_MITIGATIONS" around it. Those
IS_ENABLED(CONFIG_RETPOLINE) || IS_ENABLED(CONFIG_SLS))
"complex" conditionals may also be annoying, but dammit, they are
important documentation about why we do those things, and unlike just
comments that will inevitably bit-rot, they have semantics and get
tested.
Linus
On Thu, Oct 05, 2023 at 11:29:02AM -0700, Linus Torvalds wrote:
> ...
> "complex" conditionals may also be annoying, but dammit, they are
> important documentation about why we do those things, and unlike just
> comments that will inevitably bit-rot, they have semantics and get
> tested.
Thanks for explaining - it does make sense to me.
So, from the looks of it, we're halfway there:
- SPECULATION_MITIGATIONS is there for people who want to whack off the
whole crap
- the separate Kconfig switches are for people who want to do
a finer-grained control. And yeah, they might be annoying the first
time but you do them once and then you use the .config forever, like
with anything else.
So yeah, sounds like a plan. Breno, please add Linus' explanation to the
commit message why we're doing it this way, when sending your new
version.
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
On Fri, Oct 06, 2023 at 11:54:10AM +0200, Borislav Petkov wrote:
> On Thu, Oct 05, 2023 at 11:29:02AM -0700, Linus Torvalds wrote:
> > ...
> > "complex" conditionals may also be annoying, but dammit, they are
> > important documentation about why we do those things, and unlike just
> > comments that will inevitably bit-rot, they have semantics and get
> > tested.
>
> Thanks for explaining - it does make sense to me.
Thanks for clarifying it.
> So, from the looks of it, we're halfway there:
>
> - SPECULATION_MITIGATIONS is there for people who want to whack off the
> whole crap
>
> - the separate Kconfig switches are for people who want to do
> a finer-grained control. And yeah, they might be annoying the first
> time but you do them once and then you use the .config forever, like
> with anything else.
>
> So yeah, sounds like a plan. Breno, please add Linus' explanation to the
> commit message why we're doing it this way, when sending your new
> version.
Sure, I will update the version 3 of the patchset[1] and add Linus'
explanation plus some new mitigation that showed up in the meantime.
[1] https://lore.kernel.org/all/[email protected]/