From 5a5e587b8dd32b7656f156dd044827ade4f14f2f Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: May 30 2022 12:17:55 +0000 Subject: KVM: x86/speculation: Disable Fill buffer clear within guests (bsc#1199650 CVE-2022-21166 CVE-2022-21127 CVE-2022-21123 CVE-2022-21125 CVE-2022-21180). --- diff --git a/patches.suse/KVM-x86-speculation-Disable-Fill-buffer-clear-within-guests.patch b/patches.suse/KVM-x86-speculation-Disable-Fill-buffer-clear-within-guests.patch new file mode 100644 index 0000000..ba44e16 --- /dev/null +++ b/patches.suse/KVM-x86-speculation-Disable-Fill-buffer-clear-within-guests.patch @@ -0,0 +1,203 @@ +From: Pawan Gupta +Date: Thu, 19 May 2022 20:35:15 -0700 +Subject: KVM: x86/speculation: Disable Fill buffer clear within guests +Git-commit: 027bbb884be006b05d9c577d6401686053aa789e +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git +Patch-mainline: Queued in tip for v5.19 +References: bsc#1199650 CVE-2022-21166 CVE-2022-21127 CVE-2022-21123 CVE-2022-21125 CVE-2022-21180 + +The enumeration of MD_CLEAR in CPUID(EAX=7,ECX=0).EDX{bit 10} is not an +accurate indicator on all CPUs of whether the VERW instruction will +overwrite fill buffers. FB_CLEAR enumeration in +IA32_ARCH_CAPABILITIES{bit 17} covers the case of CPUs that are not +vulnerable to MDS/TAA, indicating that microcode does overwrite fill +buffers. + +Guests running in VMM environments may not be aware of all the +capabilities/vulnerabilities of the host CPU. Specifically, a guest may +apply MDS/TAA mitigations when a virtual CPU is enumerated as vulnerable +to MDS/TAA even when the physical CPU is not. On CPUs that enumerate +FB_CLEAR_CTRL the VMM may set FB_CLEAR_DIS to skip overwriting of fill +buffers by the VERW instruction. This is done by setting FB_CLEAR_DIS +during VMENTER and resetting on VMEXIT. For guests that enumerate +FB_CLEAR (explicitly asking for fill buffer clear capability) the VMM +will not use FB_CLEAR_DIS. + +Irrespective of guest state, host overwrites CPU buffers before VMENTER +to protect itself from an MMIO capable guest, as part of mitigation for +MMIO Stale Data vulnerabilities. + +Signed-off-by: Pawan Gupta +Signed-off-by: Borislav Petkov +--- + arch/x86/include/asm/msr-index.h | 6 +++ + arch/x86/kvm/vmx/vmx.c | 69 +++++++++++++++++++++++++++++++++++++++ + arch/x86/kvm/vmx/vmx.h | 2 + + arch/x86/kvm/x86.c | 3 + + 4 files changed, 80 insertions(+) + +--- a/arch/x86/include/asm/msr-index.h ++++ b/arch/x86/include/asm/msr-index.h +@@ -133,6 +133,11 @@ + * VERW clears CPU fill buffer + * even on MDS_NO CPUs. + */ ++#define ARCH_CAP_FB_CLEAR_CTRL BIT(18) /* ++ * MSR_IA32_MCU_OPT_CTRL[FB_CLEAR_DIS] ++ * bit available to control VERW ++ * behavior. ++ */ + + #define MSR_IA32_FLUSH_CMD 0x0000010b + #define L1D_FLUSH BIT(0) /* +@@ -150,6 +155,7 @@ + /* SRBDS support */ + #define MSR_IA32_MCU_OPT_CTRL 0x00000123 + #define RNGDS_MITG_DIS BIT(0) ++#define FB_CLEAR_DIS BIT(3) /* CPU Fill buffer clear disable */ + + #define MSR_IA32_SYSENTER_CS 0x00000174 + #define MSR_IA32_SYSENTER_ESP 0x00000175 +--- a/arch/x86/kvm/vmx/vmx.c ++++ b/arch/x86/kvm/vmx/vmx.c +@@ -205,6 +205,9 @@ static const struct { + #define L1D_CACHE_ORDER 4 + static void *vmx_l1d_flush_pages; + ++/* Control for disabling CPU Fill buffer clear */ ++static bool __read_mostly vmx_fb_clear_ctrl_available; ++ + static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf) + { + struct page *page; +@@ -331,6 +334,60 @@ static int vmentry_l1d_flush_get(char *s + return sprintf(s, "%s\n", vmentry_l1d_param[l1tf_vmx_mitigation].option); + } + ++static void vmx_setup_fb_clear_ctrl(void) ++{ ++ u64 msr; ++ ++ if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES) && ++ !boot_cpu_has_bug(X86_BUG_MDS) && ++ !boot_cpu_has_bug(X86_BUG_TAA)) { ++ rdmsrl(MSR_IA32_ARCH_CAPABILITIES, msr); ++ if (msr & ARCH_CAP_FB_CLEAR_CTRL) ++ vmx_fb_clear_ctrl_available = true; ++ } ++} ++ ++static __always_inline void vmx_disable_fb_clear(struct vcpu_vmx *vmx) ++{ ++ u64 msr; ++ ++ if (!vmx->disable_fb_clear) ++ return; ++ ++ rdmsrl(MSR_IA32_MCU_OPT_CTRL, msr); ++ msr |= FB_CLEAR_DIS; ++ wrmsrl(MSR_IA32_MCU_OPT_CTRL, msr); ++ /* Cache the MSR value to avoid reading it later */ ++ vmx->msr_ia32_mcu_opt_ctrl = msr; ++} ++ ++static __always_inline void vmx_enable_fb_clear(struct vcpu_vmx *vmx) ++{ ++ if (!vmx->disable_fb_clear) ++ return; ++ ++ vmx->msr_ia32_mcu_opt_ctrl &= ~FB_CLEAR_DIS; ++ wrmsrl(MSR_IA32_MCU_OPT_CTRL, vmx->msr_ia32_mcu_opt_ctrl); ++} ++ ++static void vmx_update_fb_clear_dis(struct kvm_vcpu *vcpu, struct vcpu_vmx *vmx) ++{ ++ vmx->disable_fb_clear = vmx_fb_clear_ctrl_available; ++ ++ /* ++ * If guest will not execute VERW, there is no need to set FB_CLEAR_DIS ++ * at VMEntry. Skip the MSR read/write when a guest has no use case to ++ * execute VERW. ++ */ ++ if ((vcpu->arch.arch_capabilities & ARCH_CAP_FB_CLEAR) || ++ ((vcpu->arch.arch_capabilities & ARCH_CAP_MDS_NO) && ++ (vcpu->arch.arch_capabilities & ARCH_CAP_TAA_NO) && ++ (vcpu->arch.arch_capabilities & ARCH_CAP_PSDP_NO) && ++ (vcpu->arch.arch_capabilities & ARCH_CAP_FBSDP_NO) && ++ (vcpu->arch.arch_capabilities & ARCH_CAP_SBDR_SSDP_NO))) ++ vmx->disable_fb_clear = false; ++} ++ + static const struct kernel_param_ops vmentry_l1d_flush_ops = { + .set = vmentry_l1d_flush_set, + .get = vmentry_l1d_flush_get, +@@ -2179,6 +2236,10 @@ static int vmx_set_msr(struct kvm_vcpu * + ret = kvm_set_msr_common(vcpu, msr_info); + } + ++ /* FB_CLEAR may have changed, also update the FB_CLEAR_DIS behavior */ ++ if (msr_index == MSR_IA32_ARCH_CAPABILITIES) ++ vmx_update_fb_clear_dis(vcpu, vmx); ++ + return ret; + } + +@@ -4411,6 +4472,8 @@ static void vmx_vcpu_reset(struct kvm_vc + vpid_sync_context(vmx->vpid); + if (init_event) + vmx_clear_hlt(vcpu); ++ ++ vmx_update_fb_clear_dis(vcpu, vmx); + } + + static void enable_irq_window(struct kvm_vcpu *vcpu) +@@ -6746,6 +6809,8 @@ static void vmx_vcpu_run(struct kvm_vcpu + kvm_arch_has_assigned_device(vcpu->kvm)) + mds_clear_cpu_buffers(); + ++ vmx_disable_fb_clear(vmx); ++ + if (vcpu->arch.cr2 != read_cr2()) + write_cr2(vcpu->arch.cr2); + +@@ -6754,6 +6819,8 @@ static void vmx_vcpu_run(struct kvm_vcpu + + vcpu->arch.cr2 = read_cr2(); + ++ vmx_enable_fb_clear(vmx); ++ + /* + * We do not use IBRS in the kernel. If this vCPU has used the + * SPEC_CTRL MSR it may have left it on; save the value and +@@ -8251,6 +8318,8 @@ static int __init vmx_init(void) + } + } + ++ vmx_setup_fb_clear_ctrl(); ++ + #ifdef CONFIG_KEXEC_CORE + rcu_assign_pointer(crash_vmclear_loaded_vmcss, + crash_vmclear_local_loaded_vmcss); +--- a/arch/x86/kvm/vmx/vmx.h ++++ b/arch/x86/kvm/vmx/vmx.h +@@ -285,6 +285,8 @@ struct vcpu_vmx { + u64 msr_ia32_feature_control; + u64 msr_ia32_feature_control_valid_bits; + u64 ept_pointer; ++ u64 msr_ia32_mcu_opt_ctrl; ++ bool disable_fb_clear; + + struct pt_desc pt_desc; + }; +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -1310,6 +1310,9 @@ static u64 kvm_get_arch_capabilities(voi + */ + } + ++ /* Guests don't need to know "Fill buffer clear control" exists */ ++ data &= ~ARCH_CAP_FB_CLEAR_CTRL; ++ + return data; + } + diff --git a/series.conf b/series.conf index efce988..578dacc 100644 --- a/series.conf +++ b/series.conf @@ -23046,6 +23046,7 @@ patches.suse/x86-speculation-mmio-Add-sysfs-reporting-for-Processor-MMIO-Stale-Data.patch patches.suse/x86-speculation-srbds-Update-SRBDS-mitigation-selection.patch patches.suse/x86-speculation-mmio-Reuse-SRBDS-mitigation-for-SBDS.patch + patches.suse/KVM-x86-speculation-Disable-Fill-buffer-clear-within-guests.patch ######################################################## # kbuild/module infrastructure fixes