* [MODERATED] [PATCH v9] Command-line
@ 2018-07-11 0:00 Jiri Kosina
2018-07-11 5:29 ` [MODERATED] " Josh Poimboeuf
2018-07-11 17:42 ` Konrad Rzeszutek Wilk
0 siblings, 2 replies; 3+ messages in thread
From: Jiri Kosina @ 2018-07-11 0:00 UTC (permalink / raw)
To: speck
Introduce the 'l1tf=' kernel command line option to allow for boot-time
switching of mitigation that is used on processors affected by L1TF.
The possible values are:
full
Provides all available mitigations for the L1TF vulnerability. Disables
SMT and enable all mitigations in the hypervisors. SMT control via
/sys/devices/system/cpu/smt/control is still possible after boot.
Hypervisors will issue a warning when the first VM is started in
a pontetially insecure configuration, i.e. SMT enabled or L1D flush
disabled.
full,force
Same as 'full', but disables SMT control. Implies the 'nosmt=force'
command line option. (I.e. sysfs control of SMT is disabled.)
flush
Leaves SMT enabled and enables the conditional hypervisor mitigation.
Hypervisors will issue a warning when the first VM is started in a
potentially insecure configuration, i.e. SMT enabled or L1D flush
disabled.
flush,nowarn
Same as 'flush', but hypervisors will not warn when
a VM is started in a potentially insecure configuration.
off
Disables hypervisor mitigations and doesn't emit any warnings.
Default is 'flush'.
Let KVM adhere to these semantics, which means:
- 'lt1f=full,force' : start performing L1D flushes
- 'l1tf=full' : start performing L1D flushes,
warn on VM start if SMT has
been runtime enabled
- 'l1tf=flush' : start performing L1D flushes,
warn on VM start if SMT is on
- 'l1tf=flush,nowarn' : no extra action is taken
- 'l1tf=off' : L1D flushes are not performed,
no warnings are issued
KVM always override the L1D flushing behavior using its 'vmentry_l1d_flush'
module parameter.
This makes KVM's private 'nosmt' option redundant, and as it is a bit
non-systematic anyway (this is something to control globally, not on hypervisor
level). Remove that option.
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
v8->v9:
- after a bit of discussion, switch to L1D flushes being the
default
- rename the option names (novirt -> flush) (Josh)
- introduce 'off' option that turns the flushes off
- remove the Reviewed-by: gathered so far, as we're changing
semantics
v7->v8:
- adjusted the sysfs output for l1tf_vmx_states to avoid
potentially confusing "mostly protected"
- L1TF_MSG_SMT is now printed _once()
- fixed typos and stylistic issues pointed out by Josh and Ingo
both in commitlog and documentation
- fixed code stylistic issues (ordering of the enum constants)
pointed out by Ingo
- fixed comment typo in vmx_l1d_flush()
- added Ingo's Reviewed-by:
v6->v7:
- Fixed the CVE number
- Slightly reworded the parameter description
- Take the l1tf command line parameter into account when
initializing the VMX L1TF mitigation and expose the
vmx mitigation state to the core.
- Make the sysfs l1tf file show the VMX mitigation state
in detail.
v5->v6:
- 'full' implies 'nosmt', 'full,force' implies nosmt=force;
print KVM warnings accordingly (one state more, and having
bitflags would be needed for clarity)
- now that we have full and full,force, drop KVM's private
nosmt option
- drop compile-time option to chose the default default :)
- typo/grammar fixes
v4->v5:
- rebase on top of KVM bundle
v3->v4:
- unconfuse the meaning of 'off', both in the documentation and in
the code (spotted by Josh)
v2->v3:
- provide l1tf=[full,novirt,off]
- provide config option to chose the default
- let KVM warn in novirt case
v1->v2
- add forgotten dependency on X86_BUG_L1TF
Documentation/admin-guide/kernel-parameters.txt | 45 +++++++++++--
arch/x86/include/asm/processor.h | 11 ++++
arch/x86/include/asm/vmx.h | 9 +++
arch/x86/kernel/cpu/bugs.c | 88 ++++++++++++++++++++++++-
arch/x86/kvm/vmx.c | 52 ++++++++++-----
include/linux/cpu.h | 2 +
kernel/cpu.c | 9 ++-
7 files changed, 188 insertions(+), 28 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 4f790566ad91..8411ad1348b1 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1946,12 +1946,6 @@
[KVM,ARM] Allow use of GICv4 for direct injection of
LPIs.
- kvm-intel.nosmt=[KVM,Intel] If the L1TF CPU bug is present (CVE-2018-3620)
- and the system has SMT (aka Hyper-Threading) enabled then
- don't allow guests to be created.
-
- Default is 0 (allow guests to be created).
-
kvm-intel.ept= [KVM,Intel] Disable extended page tables
(virtualized MMU) support on capable Intel chips.
Default is 1 (enabled)
@@ -1989,6 +1983,45 @@
feature (tagged TLBs) on capable Intel chips.
Default is 1 (enabled)
+ l1tf= [X86] Control mitigation of the L1TF vulnerability on
+ affected CPUs
+
+ The kernel PTE inversion protection is unconditionally
+ enabled and cannot be disabled.
+
+ full
+ Provides all available mitigations for the L1TF
+ vulnerability. Disables SMT and enable all
+ mitigations in the hypervisors. SMT control via
+ /sys/devices/system/cpu/smt/control is still
+ possible after boot. Hypervisors will issue a
+ warning when the first VM is started in a
+ pontetially insecure configuration, i.e. SMT
+ enabled or L1D flush disabled.
+
+ full,force
+ Same as 'full', but disables SMT control.
+ Implies the 'nosmt=force' command line option.
+ (I.e. sysfs control of SMT is disabled.)
+
+ flush
+ Leaves SMT enabled while enabling the conditional
+ hypervisor mitigation. Hypervisors will issue a
+ warning when the first VM is started in a
+ potentially insecure configuration, i.e. SMT
+ enabled or L1D flush disabled.
+
+ flush,nowarn
+ Same as 'flush', but hypervisors will not
+ warn when a VM is started in a potentially
+ insecure configuration.
+
+ off
+ Disables hypervisor mitigations and doesn't
+ emit any warnings.
+
+ Default is 'novirt'.
+
l2cr= [PPC]
l3cr= [PPC]
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 7e3ac5eedcd6..897870062eff 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -982,4 +982,15 @@ bool xen_set_default_idle(void);
void stop_this_cpu(void *dummy);
void df_debug(struct pt_regs *regs, long error_code);
void microcode_check(void);
+
+enum l1tf_mitigations {
+ L1TF_MITIGATION_OFF,
+ L1TF_MITIGATION_FLUSH_NOWARN,
+ L1TF_MITIGATION_FLUSH,
+ L1TF_MITIGATION_FULL,
+ L1TF_MITIGATION_FULL_FORCE
+};
+
+extern enum l1tf_mitigations l1tf_mitigation;
+
#endif /* _ASM_X86_PROCESSOR_H */
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 425e6b8b9547..4888ec66ffc7 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -573,4 +573,13 @@ enum vm_instruction_error_number {
VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID = 28,
};
+/* These MUST be in sync with vmentry_l1d_param order. */
+enum vmx_l1d_flush_state {
+ VMENTER_L1D_FLUSH_NEVER,
+ VMENTER_L1D_FLUSH_COND,
+ VMENTER_L1D_FLUSH_ALWAYS,
+};
+
+extern enum vmx_l1d_flush_state l1tf_vmx_mitigation;
+
#endif
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 50500cea6eba..cc5777ec88fa 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -23,6 +23,7 @@
#include <asm/fpu/internal.h>
#include <asm/msr.h>
#include <asm/paravirt.h>
+#include <asm/vmx.h>
#include <asm/alternative.h>
#include <asm/pgtable.h>
#include <asm/set_memory.h>
@@ -657,6 +658,20 @@ void x86_spec_ctrl_setup_ap(void)
#undef pr_fmt
#define pr_fmt(fmt) "L1TF: " fmt
+
+
+/* Default mitigation for L1TF-affected CPUs */
+enum l1tf_mitigations l1tf_mitigation __ro_after_init = L1TF_MITIGATION_FLUSH;
+#if IS_ENABLED(CONFIG_KVM_INTEL)
+EXPORT_SYMBOL_GPL(l1tf_mitigation);
+
+/* Initialize it to unknown which indicates that VMX has not been initialized */
+#define L1TF_VMX_UNKNOWN INT_MAX
+
+enum vmx_l1d_flush_state l1tf_vmx_mitigation = L1TF_VMX_UNKNOWN;
+EXPORT_SYMBOL_GPL(l1tf_vmx_mitigation);
+#endif
+
static void __init l1tf_select_mitigation(void)
{
u64 half_pa;
@@ -664,6 +679,19 @@ static void __init l1tf_select_mitigation(void)
if (!boot_cpu_has_bug(X86_BUG_L1TF))
return;
+ switch (l1tf_mitigation) {
+ case L1TF_MITIGATION_OFF:
+ case L1TF_MITIGATION_FLUSH_NOWARN:
+ case L1TF_MITIGATION_FLUSH:
+ break;
+ case L1TF_MITIGATION_FULL:
+ cpu_smt_disable(false);
+ break;
+ case L1TF_MITIGATION_FULL_FORCE:
+ cpu_smt_disable(true);
+ break;
+ }
+
#if CONFIG_PGTABLE_LEVELS == 2
pr_warn("Kernel not compiled for PAE. No mitigation for L1TF\n");
return;
@@ -682,10 +710,66 @@ static void __init l1tf_select_mitigation(void)
setup_force_cpu_cap(X86_FEATURE_L1TF_PTEINV);
}
+
+static int __init l1tf_cmdline(char *str)
+{
+ if (!boot_cpu_has_bug(X86_BUG_L1TF))
+ return 0;
+
+ if (!str)
+ return 0;
+
+ if (!strcmp(str, "off"))
+ l1tf_mitigation = L1TF_MITIGATION_OFF;
+ else if (!strcmp(str, "novirt,nowarn"))
+ l1tf_mitigation = L1TF_MITIGATION_FLUSH_NOWARN;
+ else if (!strcmp(str, "novirt"))
+ l1tf_mitigation = L1TF_MITIGATION_FLUSH;
+ else if (!strcmp(str, "full"))
+ l1tf_mitigation = L1TF_MITIGATION_FULL;
+ else if (!strcmp(str, "full,force"))
+ l1tf_mitigation = L1TF_MITIGATION_FULL_FORCE;
+
+ return 0;
+}
+early_param("l1tf", l1tf_cmdline);
+
#undef pr_fmt
#ifdef CONFIG_SYSFS
+static const char *l1tf_states[] = {
+ [L1TF_MITIGATION_OFF] = "Mitigation: Page Table Inversion",
+ [L1TF_MITIGATION_FLUSH_NOWARN] = "Mitigation: Page Table Inversion",
+ [L1TF_MITIGATION_FLUSH] = "Mitigation: Page Table Inversion",
+ [L1TF_MITIGATION_FULL] = "Mitigation: Full",
+ [L1TF_MITIGATION_FULL_FORCE] = "Mitigation: Full [force]"
+};
+
+#if IS_ENABLED(CONFIG_KVM_INTEL)
+static const char *l1tf_vmx_states[] = {
+ [VMENTER_L1D_FLUSH_NEVER] = "vulnerable",
+ [VMENTER_L1D_FLUSH_COND] = "conditional cache flushes",
+ [VMENTER_L1D_FLUSH_ALWAYS] = "cache flushes"
+};
+
+static ssize_t l1tf_show_state(char *buf)
+{
+ if (l1tf_vmx_mitigation == L1TF_VMX_UNKNOWN)
+ return sprintf(buf, "%s\n", l1tf_states[l1tf_mitigation]);
+
+ return sprintf(buf, "%s, VMX: SMT %s; L1D %s\n",
+ l1tf_states[l1tf_mitigation],
+ cpu_smt_control == CPU_SMT_ENABLED ? "vulnerable" : "disabled",
+ l1tf_vmx_states[l1tf_vmx_mitigation]);
+}
+#else
+static ssize_t l1tf_show_state(char *buf)
+{
+ return sprintf(buf, "%s\n", l1tf_states[l1tf_mitigation]);
+}
+#endif
+
static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
char *buf, unsigned int bug)
{
@@ -712,9 +796,7 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);
case X86_BUG_L1TF:
- if (boot_cpu_has(X86_FEATURE_L1TF_PTEINV))
- return sprintf(buf, "Mitigation: Page Table Inversion\n");
- break;
+ return l1tf_show_state(buf);
default:
break;
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index eb7c207a3bc3..cf305ccf73aa 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -71,9 +71,6 @@ static const struct x86_cpu_id vmx_cpu_id[] = {
};
MODULE_DEVICE_TABLE(x86cpu, vmx_cpu_id);
-static bool __read_mostly nosmt;
-module_param(nosmt, bool, S_IRUGO);
-
static bool __read_mostly enable_vpid = 1;
module_param_named(vpid, enable_vpid, bool, 0444);
@@ -193,13 +190,6 @@ extern const ulong vmx_return;
static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush);
-/* These MUST be in sync with vmentry_l1d_param order. */
-enum vmx_l1d_flush_state {
- VMENTER_L1D_FLUSH_NEVER,
- VMENTER_L1D_FLUSH_COND,
- VMENTER_L1D_FLUSH_ALWAYS,
-};
-
static enum vmx_l1d_flush_state __read_mostly vmentry_l1d_flush = VMENTER_L1D_FLUSH_COND;
static const struct {
@@ -9631,7 +9621,7 @@ static void vmx_l1d_flush(struct kvm_vcpu *vcpu)
* If the CPU has the flush MSR then clear the flush bit because
* 'always' mode is handled via the MSR save list.
*
- * If the MSR is not avaibable then act depending on the mitigation
+ * If the MSR is not available then act depending on the mitigation
* mode: If 'flush always', keep the flush bit set, otherwise clear
* it.
*
@@ -10539,19 +10529,36 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
return ERR_PTR(err);
}
-#define L1TF_MSG "SMT enabled with L1TF CPU bug present. Refer to CVE-2018-3620 for details.\n"
+#define L1TF_MSG_SMT "L1TF CPU bug present and SMT on, data leak possible. Refer to CVE-2018-3646 for details.\n"
+#define L1TF_MSG_L1D "L1TF CPU bug present and virtualization mitigation disabled, data leak possible. Refer to CVE-2018-3646 for details.\n"
static int vmx_vm_init(struct kvm *kvm)
{
if (!ple_gap)
kvm->arch.pause_in_guest = true;
- if (boot_cpu_has(X86_BUG_L1TF) && cpu_smt_control == CPU_SMT_ENABLED) {
- if (nosmt) {
- pr_err(L1TF_MSG);
- return -EOPNOTSUPP;
+ if (boot_cpu_has(X86_BUG_L1TF)) {
+ switch (l1tf_mitigation) {
+ case L1TF_MITIGATION_OFF:
+ case L1TF_MITIGATION_FLUSH_NOWARN:
+ /* 'I explicitly don't care' is set */
+ break;
+ case L1TF_MITIGATION_FLUSH:
+ case L1TF_MITIGATION_FULL:
+ /*
+ * Warn upon starting the first VM in a
+ * potentially insecure environment.
+ */
+ if (cpu_smt_control == CPU_SMT_ENABLED)
+ pr_warn_once(L1TF_MSG_SMT);
+ if (vmentry_l1d_flush == VMENTER_L1D_FLUSH_NEVER)
+ pr_warn_once(L1TF_MSG_L1D);
+ break;
+ case L1TF_MITIGATION_FULL_FORCE:
+ if (vmentry_l1d_flush == VMENTER_L1D_FLUSH_NEVER)
+ pr_warn_once(L1TF_MSG_L1D);
+ break;
}
- pr_warn(L1TF_MSG);
}
return 0;
}
@@ -13235,6 +13242,17 @@ static int __init vmx_setup_l1d_flush(void)
{
struct page *page;
+ /* Take the l1tf= command line parameter into account */
+ switch (l1tf_mitigation) {
+ case L1TF_MITIGATION_OFF:
+ vmentry_l1d_flush = VMENTER_L1D_FLUSH_NEVER;
+ break;
+ default:
+ break;
+ }
+
+ l1tf_vmx_mitigation = vmentry_l1d_flush;
+
if (vmentry_l1d_flush == VMENTER_L1D_FLUSH_NEVER ||
!boot_cpu_has_bug(X86_BUG_L1TF) ||
vmx_l1d_use_msr_save_list())
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 7532cbf27b1d..c9b23ad27b38 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -177,8 +177,10 @@ enum cpuhp_smt_control {
#if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT)
extern enum cpuhp_smt_control cpu_smt_control;
+extern void cpu_smt_disable(bool force);
#else
# define cpu_smt_control (CPU_SMT_ENABLED)
+static inline void cpu_smt_disable(bool force) { }
#endif
#endif /* _LINUX_CPU_H_ */
diff --git a/kernel/cpu.c b/kernel/cpu.c
index d79e24df2420..7a31326135af 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -347,13 +347,18 @@ EXPORT_SYMBOL_GPL(cpu_hotplug_enable);
enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED;
EXPORT_SYMBOL_GPL(cpu_smt_control);
-static int __init smt_cmdline_disable(char *str)
+void __init cpu_smt_disable(bool force)
{
cpu_smt_control = CPU_SMT_DISABLED;
- if (str && !strcmp(str, "force")) {
+ if (force) {
pr_info("SMT: Force disabled\n");
cpu_smt_control = CPU_SMT_FORCE_DISABLED;
}
+}
+
+static int __init smt_cmdline_disable(char *str)
+{
+ cpu_smt_disable(str && !strcmp(str, "force"));
return 0;
}
early_param("nosmt", smt_cmdline_disable);
--
Jiri Kosina
SUSE Labs
^ permalink raw reply related [flat|nested] 3+ messages in thread* [MODERATED] Re: [PATCH v9] Command-line
2018-07-11 0:00 [MODERATED] [PATCH v9] Command-line Jiri Kosina
@ 2018-07-11 5:29 ` Josh Poimboeuf
2018-07-11 17:42 ` Konrad Rzeszutek Wilk
1 sibling, 0 replies; 3+ messages in thread
From: Josh Poimboeuf @ 2018-07-11 5:29 UTC (permalink / raw)
To: speck
On Wed, Jul 11, 2018 at 02:00:46AM +0200, speck for Jiri Kosina wrote:
> @@ -1989,6 +1983,45 @@
> feature (tagged TLBs) on capable Intel chips.
> Default is 1 (enabled)
>
> + l1tf= [X86] Control mitigation of the L1TF vulnerability on
> + affected CPUs
> +
> + The kernel PTE inversion protection is unconditionally
> + enabled and cannot be disabled.
> +
> + full
> + Provides all available mitigations for the L1TF
> + vulnerability. Disables SMT and enable all
> + mitigations in the hypervisors. SMT control via
> + /sys/devices/system/cpu/smt/control is still
> + possible after boot. Hypervisors will issue a
> + warning when the first VM is started in a
> + pontetially insecure configuration, i.e. SMT
> + enabled or L1D flush disabled.
> +
> + full,force
> + Same as 'full', but disables SMT control.
> + Implies the 'nosmt=force' command line option.
> + (I.e. sysfs control of SMT is disabled.)
> +
> + flush
> + Leaves SMT enabled while enabling the conditional
> + hypervisor mitigation. Hypervisors will issue a
> + warning when the first VM is started in a
> + potentially insecure configuration, i.e. SMT
> + enabled or L1D flush disabled.
> +
> + flush,nowarn
> + Same as 'flush', but hypervisors will not
> + warn when a VM is started in a potentially
> + insecure configuration.
> +
> + off
> + Disables hypervisor mitigations and doesn't
> + emit any warnings.
> +
> + Default is 'novirt'.
Default is 'flush'.
> +static ssize_t l1tf_show_state(char *buf)
> +{
> + if (l1tf_vmx_mitigation == L1TF_VMX_UNKNOWN)
> + return sprintf(buf, "%s\n", l1tf_states[l1tf_mitigation]);
> +
> + return sprintf(buf, "%s, VMX: SMT %s; L1D %s\n",
> + l1tf_states[l1tf_mitigation],
> + cpu_smt_control == CPU_SMT_ENABLED ? "vulnerable" : "disabled",
> + l1tf_vmx_states[l1tf_vmx_mitigation]);
I would swap the semicolon and the comma, so instead of:
Mitigation: Page Table Inversion, VMX: SMT disabled; L1D conditional cache flushes
it shows:
Mitigation: Page Table Inversion; VMX: SMT disabled, L1D conditional cache flushes
so that the host mitigation is a little more clearly delineated from the
VMX mitigation.
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
--
Josh
^ permalink raw reply [flat|nested] 3+ messages in thread* [MODERATED] Re: [PATCH v9] Command-line
2018-07-11 0:00 [MODERATED] [PATCH v9] Command-line Jiri Kosina
2018-07-11 5:29 ` [MODERATED] " Josh Poimboeuf
@ 2018-07-11 17:42 ` Konrad Rzeszutek Wilk
1 sibling, 0 replies; 3+ messages in thread
From: Konrad Rzeszutek Wilk @ 2018-07-11 17:42 UTC (permalink / raw)
To: speck
> @@ -1989,6 +1983,45 @@
> feature (tagged TLBs) on capable Intel chips.
> Default is 1 (enabled)
>
> + l1tf= [X86] Control mitigation of the L1TF vulnerability on
> + affected CPUs
> +
> + The kernel PTE inversion protection is unconditionally
> + enabled and cannot be disabled.
> +
> + full
> + Provides all available mitigations for the L1TF
> + vulnerability. Disables SMT and enable all
> + mitigations in the hypervisors. SMT control via
> + /sys/devices/system/cpu/smt/control is still
> + possible after boot. Hypervisors will issue a
> + warning when the first VM is started in a
> + pontetially insecure configuration, i.e. SMT
s/pontetially/potentially/
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2018-07-11 17:43 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-07-11 0:00 [MODERATED] [PATCH v9] Command-line Jiri Kosina
2018-07-11 5:29 ` [MODERATED] " Josh Poimboeuf
2018-07-11 17:42 ` Konrad Rzeszutek Wilk
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.