Commit 2decbf52 authored by Jiri Kosina's avatar Jiri Kosina Committed by Greg Kroah-Hartman

x86/bugs, kvm: Introduce boot-time control of L1TF mitigations

commit d90a7a0e upstream

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 enables 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 potentially 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. sysfs control of SMT and the hypervisor flush
	control 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,nosmt
	Disables SMT and enables the conditional hypervisor mitigation. SMT
	control via /sys/devices/system/cpu/smt/control is still possible
	after boot. If SMT is reenabled or flushing disabled at runtime
	hypervisors will issue a warning.

  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'	: Performe L1D flushes. No runtime control
    			  possible.

  - 'l1tf=full'
  - 'l1tf-flush'
  - 'l1tf=flush,nosmt'	: Perform L1D flushes and warn on VM start if
			  SMT has been runtime enabled or L1D flushing
			  has been run-time enabled

  - 'l1tf=flush,nowarn'	: Perform L1D flushes and no warnings are emitted.

  - 'l1tf=off'		: L1D flushes are not performed and no warnings
			  are emitted.

KVM can always override the L1D flushing behavior using its 'vmentry_l1d_flush'
module parameter except when lt1f=full,force is set.

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.

Add the missing Documentation entry for the l1tf vulnerability sysfs file
while at it.
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Tested-by: default avatarJiri Kosina <jkosina@suse.cz>
Reviewed-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Link: https://lkml.kernel.org/r/20180713142323.202758176@linutronix.deSigned-off-by: default avatarDavid Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 929d3b2e
...@@ -356,6 +356,7 @@ What: /sys/devices/system/cpu/vulnerabilities ...@@ -356,6 +356,7 @@ What: /sys/devices/system/cpu/vulnerabilities
/sys/devices/system/cpu/vulnerabilities/spectre_v1 /sys/devices/system/cpu/vulnerabilities/spectre_v1
/sys/devices/system/cpu/vulnerabilities/spectre_v2 /sys/devices/system/cpu/vulnerabilities/spectre_v2
/sys/devices/system/cpu/vulnerabilities/spec_store_bypass /sys/devices/system/cpu/vulnerabilities/spec_store_bypass
/sys/devices/system/cpu/vulnerabilities/l1tf
Date: January 2018 Date: January 2018
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org> Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
Description: Information about CPU vulnerabilities Description: Information about CPU vulnerabilities
...@@ -368,6 +369,9 @@ Description: Information about CPU vulnerabilities ...@@ -368,6 +369,9 @@ Description: Information about CPU vulnerabilities
"Vulnerable" CPU is affected and no mitigation in effect "Vulnerable" CPU is affected and no mitigation in effect
"Mitigation: $M" CPU is affected and mitigation $M is in effect "Mitigation: $M" CPU is affected and mitigation $M is in effect
Details about the l1tf file can be found in
Documentation/admin-guide/l1tf.rst
What: /sys/devices/system/cpu/smt What: /sys/devices/system/cpu/smt
/sys/devices/system/cpu/smt/active /sys/devices/system/cpu/smt/active
/sys/devices/system/cpu/smt/control /sys/devices/system/cpu/smt/control
......
...@@ -1989,12 +1989,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -1989,12 +1989,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
for all guests. for all guests.
Default is 1 (enabled) if in 64-bit or 32-bit PAE mode. Default is 1 (enabled) if in 64-bit or 32-bit PAE mode.
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 kvm-intel.ept= [KVM,Intel] Disable extended page tables
(virtualized MMU) support on capable Intel chips. (virtualized MMU) support on capable Intel chips.
Default is 1 (enabled) Default is 1 (enabled)
...@@ -2032,6 +2026,68 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -2032,6 +2026,68 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
feature (tagged TLBs) on capable Intel chips. feature (tagged TLBs) on capable Intel chips.
Default is 1 (enabled) 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
enables all mitigations in the
hypervisors, i.e. unconditional L1D flush.
SMT control and L1D flush control via the
sysfs interface is still possible after
boot. Hypervisors will issue a warning
when the first VM is started in a
potentially insecure configuration,
i.e. SMT enabled or L1D flush disabled.
full,force
Same as 'full', but disables SMT and L1D
flush runtime control. Implies the
'nosmt=force' command line option.
(i.e. sysfs control of SMT is disabled.)
flush
Leaves SMT enabled and enables the default
hypervisor mitigation, i.e. conditional
L1D flush.
SMT control and L1D flush control via the
sysfs interface is still possible after
boot. 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,nosmt
Disables SMT and enables the default
hypervisor mitigation.
SMT control and L1D flush control via the
sysfs interface is still possible after
boot. 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'.
For details see: Documentation/admin-guide/l1tf.rst
l2cr= [PPC] l2cr= [PPC]
l3cr= [PPC] l3cr= [PPC]
......
...@@ -860,4 +860,16 @@ bool xen_set_default_idle(void); ...@@ -860,4 +860,16 @@ bool xen_set_default_idle(void);
void stop_this_cpu(void *dummy); void stop_this_cpu(void *dummy);
void df_debug(struct pt_regs *regs, long error_code); void df_debug(struct pt_regs *regs, long error_code);
enum l1tf_mitigations {
L1TF_MITIGATION_OFF,
L1TF_MITIGATION_FLUSH_NOWARN,
L1TF_MITIGATION_FLUSH,
L1TF_MITIGATION_FLUSH_NOSMT,
L1TF_MITIGATION_FULL,
L1TF_MITIGATION_FULL_FORCE
};
extern enum l1tf_mitigations l1tf_mitigation;
#endif /* _ASM_X86_PROCESSOR_H */ #endif /* _ASM_X86_PROCESSOR_H */
...@@ -643,7 +643,11 @@ void x86_spec_ctrl_setup_ap(void) ...@@ -643,7 +643,11 @@ void x86_spec_ctrl_setup_ap(void)
#undef pr_fmt #undef pr_fmt
#define pr_fmt(fmt) "L1TF: " 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) #if IS_ENABLED(CONFIG_KVM_INTEL)
EXPORT_SYMBOL_GPL(l1tf_mitigation);
enum vmx_l1d_flush_state l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO; enum vmx_l1d_flush_state l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO;
EXPORT_SYMBOL_GPL(l1tf_vmx_mitigation); EXPORT_SYMBOL_GPL(l1tf_vmx_mitigation);
#endif #endif
...@@ -655,6 +659,20 @@ static void __init l1tf_select_mitigation(void) ...@@ -655,6 +659,20 @@ static void __init l1tf_select_mitigation(void)
if (!boot_cpu_has_bug(X86_BUG_L1TF)) if (!boot_cpu_has_bug(X86_BUG_L1TF))
return; return;
switch (l1tf_mitigation) {
case L1TF_MITIGATION_OFF:
case L1TF_MITIGATION_FLUSH_NOWARN:
case L1TF_MITIGATION_FLUSH:
break;
case L1TF_MITIGATION_FLUSH_NOSMT:
case L1TF_MITIGATION_FULL:
cpu_smt_disable(false);
break;
case L1TF_MITIGATION_FULL_FORCE:
cpu_smt_disable(true);
break;
}
#if CONFIG_PGTABLE_LEVELS == 2 #if CONFIG_PGTABLE_LEVELS == 2
pr_warn("Kernel not compiled for PAE. No mitigation for L1TF\n"); pr_warn("Kernel not compiled for PAE. No mitigation for L1TF\n");
return; return;
...@@ -673,6 +691,32 @@ static void __init l1tf_select_mitigation(void) ...@@ -673,6 +691,32 @@ static void __init l1tf_select_mitigation(void)
setup_force_cpu_cap(X86_FEATURE_L1TF_PTEINV); 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 -EINVAL;
if (!strcmp(str, "off"))
l1tf_mitigation = L1TF_MITIGATION_OFF;
else if (!strcmp(str, "flush,nowarn"))
l1tf_mitigation = L1TF_MITIGATION_FLUSH_NOWARN;
else if (!strcmp(str, "flush"))
l1tf_mitigation = L1TF_MITIGATION_FLUSH;
else if (!strcmp(str, "flush,nosmt"))
l1tf_mitigation = L1TF_MITIGATION_FLUSH_NOSMT;
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 #undef pr_fmt
#ifdef CONFIG_SYSFS #ifdef CONFIG_SYSFS
......
...@@ -69,9 +69,6 @@ static const struct x86_cpu_id vmx_cpu_id[] = { ...@@ -69,9 +69,6 @@ static const struct x86_cpu_id vmx_cpu_id[] = {
}; };
MODULE_DEVICE_TABLE(x86cpu, 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; static bool __read_mostly enable_vpid = 1;
module_param_named(vpid, enable_vpid, bool, 0444); module_param_named(vpid, enable_vpid, bool, 0444);
...@@ -216,15 +213,31 @@ static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf) ...@@ -216,15 +213,31 @@ static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf)
{ {
struct page *page; struct page *page;
/* If set to 'auto' select 'cond' */
if (l1tf == VMENTER_L1D_FLUSH_AUTO)
l1tf = VMENTER_L1D_FLUSH_COND;
if (!enable_ept) { if (!enable_ept) {
l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_EPT_DISABLED; l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_EPT_DISABLED;
return 0; return 0;
} }
/* If set to auto use the default l1tf mitigation method */
if (l1tf == VMENTER_L1D_FLUSH_AUTO) {
switch (l1tf_mitigation) {
case L1TF_MITIGATION_OFF:
l1tf = VMENTER_L1D_FLUSH_NEVER;
break;
case L1TF_MITIGATION_FLUSH_NOWARN:
case L1TF_MITIGATION_FLUSH:
case L1TF_MITIGATION_FLUSH_NOSMT:
l1tf = VMENTER_L1D_FLUSH_COND;
break;
case L1TF_MITIGATION_FULL:
case L1TF_MITIGATION_FULL_FORCE:
l1tf = VMENTER_L1D_FLUSH_ALWAYS;
break;
}
} else if (l1tf_mitigation == L1TF_MITIGATION_FULL_FORCE) {
l1tf = VMENTER_L1D_FLUSH_ALWAYS;
}
if (l1tf != VMENTER_L1D_FLUSH_NEVER && !vmx_l1d_flush_pages && if (l1tf != VMENTER_L1D_FLUSH_NEVER && !vmx_l1d_flush_pages &&
!boot_cpu_has(X86_FEATURE_FLUSH_L1D)) { !boot_cpu_has(X86_FEATURE_FLUSH_L1D)) {
page = alloc_pages(GFP_KERNEL, L1D_CACHE_ORDER); page = alloc_pages(GFP_KERNEL, L1D_CACHE_ORDER);
...@@ -9500,16 +9513,33 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id) ...@@ -9500,16 +9513,33 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
return ERR_PTR(err); 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. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html for details.\n"
#define L1TF_MSG_L1D "L1TF CPU bug present and virtualization mitigation disabled, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html for details.\n"
static int vmx_vm_init(struct kvm *kvm) static int vmx_vm_init(struct kvm *kvm)
{ {
if (boot_cpu_has(X86_BUG_L1TF) && cpu_smt_control == CPU_SMT_ENABLED) { if (boot_cpu_has(X86_BUG_L1TF) && enable_ept) {
if (nosmt) { switch (l1tf_mitigation) {
pr_err(L1TF_MSG); case L1TF_MITIGATION_OFF:
return -EOPNOTSUPP; case L1TF_MITIGATION_FLUSH_NOWARN:
/* 'I explicitly don't care' is set */
break;
case L1TF_MITIGATION_FLUSH:
case L1TF_MITIGATION_FLUSH_NOSMT:
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 (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER)
pr_warn_once(L1TF_MSG_L1D);
break;
case L1TF_MITIGATION_FULL_FORCE:
/* Flush is enforced */
break;
} }
pr_warn(L1TF_MSG);
} }
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment