| From foo@baz Tue Aug 14 16:14:56 CEST 2018 |
| From: Jiri Kosina <jkosina@suse.cz> |
| Date: Fri, 13 Jul 2018 16:23:25 +0200 |
| Subject: x86/bugs, kvm: Introduce boot-time control of L1TF mitigations |
| |
| From: Jiri Kosina <jkosina@suse.cz> |
| |
| commit d90a7a0ec83fb86622cd7dae23255d3c50a99ec8 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: Jiri Kosina <jkosina@suse.cz> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Tested-by: Jiri Kosina <jkosina@suse.cz> |
| Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com> |
| Link: https://lkml.kernel.org/r/20180713142323.202758176@linutronix.de |
| Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| Documentation/ABI/testing/sysfs-devices-system-cpu | 4 + |
| Documentation/kernel-parameters.txt | 68 +++++++++++++++++++-- |
| arch/x86/include/asm/processor.h | 12 +++ |
| arch/x86/kernel/cpu/bugs.c | 44 +++++++++++++ |
| arch/x86/kvm/vmx.c | 56 +++++++++++++---- |
| 5 files changed, 165 insertions(+), 19 deletions(-) |
| |
| --- a/Documentation/ABI/testing/sysfs-devices-system-cpu |
| +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu |
| @@ -356,6 +356,7 @@ What: /sys/devices/system/cpu/vulnerabi |
| /sys/devices/system/cpu/vulnerabilities/spectre_v1 |
| /sys/devices/system/cpu/vulnerabilities/spectre_v2 |
| /sys/devices/system/cpu/vulnerabilities/spec_store_bypass |
| + /sys/devices/system/cpu/vulnerabilities/l1tf |
| Date: January 2018 |
| Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org> |
| Description: Information about CPU vulnerabilities |
| @@ -368,6 +369,9 @@ Description: Information about CPU vulne |
| "Vulnerable" CPU is affected and no mitigation 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 |
| /sys/devices/system/cpu/smt/active |
| /sys/devices/system/cpu/smt/control |
| --- a/Documentation/kernel-parameters.txt |
| +++ b/Documentation/kernel-parameters.txt |
| @@ -1989,12 +1989,6 @@ bytes respectively. Such letter suffixes |
| for all guests. |
| 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 |
| (virtualized MMU) support on capable Intel chips. |
| Default is 1 (enabled) |
| @@ -2032,6 +2026,68 @@ bytes respectively. Such letter suffixes |
| 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 |
| + 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] |
| |
| l3cr= [PPC] |
| --- a/arch/x86/include/asm/processor.h |
| +++ b/arch/x86/include/asm/processor.h |
| @@ -860,4 +860,16 @@ bool xen_set_default_idle(void); |
| |
| void stop_this_cpu(void *dummy); |
| 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 */ |
| --- a/arch/x86/kernel/cpu/bugs.c |
| +++ b/arch/x86/kernel/cpu/bugs.c |
| @@ -643,7 +643,11 @@ 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); |
| + |
| enum vmx_l1d_flush_state l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO; |
| EXPORT_SYMBOL_GPL(l1tf_vmx_mitigation); |
| #endif |
| @@ -655,6 +659,20 @@ static void __init l1tf_select_mitigatio |
| 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_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 |
| pr_warn("Kernel not compiled for PAE. No mitigation for L1TF\n"); |
| return; |
| @@ -673,6 +691,32 @@ static void __init l1tf_select_mitigatio |
| |
| 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 |
| |
| #ifdef CONFIG_SYSFS |
| --- a/arch/x86/kvm/vmx.c |
| +++ b/arch/x86/kvm/vmx.c |
| @@ -69,9 +69,6 @@ static const struct x86_cpu_id vmx_cpu_i |
| }; |
| 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); |
| |
| @@ -216,15 +213,31 @@ static int vmx_setup_l1d_flush(enum vmx_ |
| { |
| struct page *page; |
| |
| - /* If set to 'auto' select 'cond' */ |
| - if (l1tf == VMENTER_L1D_FLUSH_AUTO) |
| - l1tf = VMENTER_L1D_FLUSH_COND; |
| - |
| if (!enable_ept) { |
| l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_EPT_DISABLED; |
| 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 && |
| !boot_cpu_has(X86_FEATURE_FLUSH_L1D)) { |
| page = alloc_pages(GFP_KERNEL, L1D_CACHE_ORDER); |
| @@ -9500,16 +9513,33 @@ free_vcpu: |
| 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) |
| { |
| - 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) && enable_ept) { |
| + 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_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; |
| } |