Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: x86: Explicitly configure supported XSS from {svm,vmx}_set_cpu_caps()

Explicitly configure KVM's supported XSS as part of each vendor's setup
flow to fix a bug where clearing SHSTK and IBT in kvm_cpu_caps, e.g. due
to lack of CET XFEATURE support, makes kvm-intel.ko unloadable when nested
VMX is enabled, i.e. when nested=1. The late clearing results in
nested_vmx_setup_{entry,exit}_ctls() clearing VM_{ENTRY,EXIT}_LOAD_CET_STATE
when nested_vmx_setup_ctls_msrs() runs during the CPU compatibility checks,
ultimately leading to a mismatched VMCS config due to the reference config
having the CET bits set, but every CPU's "local" config having the bits
cleared.

Note, kvm_caps.supported_{xcr0,xss} are unconditionally initialized by
kvm_x86_vendor_init(), before calling into vendor code, and not referenced
between ops->hardware_setup() and their current/old location.

Fixes: 69cc3e886582 ("KVM: x86: Add XSS support for CET_KERNEL and CET_USER")
Cc: stable@vger.kernel.org
Cc: Mathias Krause <minipli@grsecurity.net>
Cc: John Allen <john.allen@amd.com>
Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
Cc: Chao Gao <chao.gao@intel.com>
Cc: Binbin Wu <binbin.wu@linux.intel.com>
Cc: Xiaoyao Li <xiaoyao.li@intel.com>
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
Link: https://patch.msgid.link/20260128014310.3255561-2-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>

+23 -13
+2
arch/x86/kvm/svm/svm.c
··· 5284 5284 */ 5285 5285 kvm_cpu_cap_clear(X86_FEATURE_BUS_LOCK_DETECT); 5286 5286 kvm_cpu_cap_clear(X86_FEATURE_MSR_IMM); 5287 + 5288 + kvm_setup_xss_caps(); 5287 5289 } 5288 5290 5289 5291 static __init int svm_hardware_setup(void)
+2
arch/x86/kvm/vmx/vmx.c
··· 8051 8051 kvm_cpu_cap_clear(X86_FEATURE_SHSTK); 8052 8052 kvm_cpu_cap_clear(X86_FEATURE_IBT); 8053 8053 } 8054 + 8055 + kvm_setup_xss_caps(); 8054 8056 } 8055 8057 8056 8058 static bool vmx_is_io_intercepted(struct kvm_vcpu *vcpu,
+17 -13
arch/x86/kvm/x86.c
··· 9953 9953 }; 9954 9954 #endif 9955 9955 9956 + void kvm_setup_xss_caps(void) 9957 + { 9958 + if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES)) 9959 + kvm_caps.supported_xss = 0; 9960 + 9961 + if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK) && 9962 + !kvm_cpu_cap_has(X86_FEATURE_IBT)) 9963 + kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL; 9964 + 9965 + if ((kvm_caps.supported_xss & XFEATURE_MASK_CET_ALL) != XFEATURE_MASK_CET_ALL) { 9966 + kvm_cpu_cap_clear(X86_FEATURE_SHSTK); 9967 + kvm_cpu_cap_clear(X86_FEATURE_IBT); 9968 + kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL; 9969 + } 9970 + } 9971 + EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_setup_xss_caps); 9972 + 9956 9973 static inline void kvm_ops_update(struct kvm_x86_init_ops *ops) 9957 9974 { 9958 9975 memcpy(&kvm_x86_ops, ops->runtime_ops, sizeof(kvm_x86_ops)); ··· 10141 10124 /* KVM always ignores guest PAT for shadow paging. */ 10142 10125 if (!tdp_enabled) 10143 10126 kvm_caps.supported_quirks &= ~KVM_X86_QUIRK_IGNORE_GUEST_PAT; 10144 - 10145 - if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES)) 10146 - kvm_caps.supported_xss = 0; 10147 - 10148 - if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK) && 10149 - !kvm_cpu_cap_has(X86_FEATURE_IBT)) 10150 - kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL; 10151 - 10152 - if ((kvm_caps.supported_xss & XFEATURE_MASK_CET_ALL) != XFEATURE_MASK_CET_ALL) { 10153 - kvm_cpu_cap_clear(X86_FEATURE_SHSTK); 10154 - kvm_cpu_cap_clear(X86_FEATURE_IBT); 10155 - kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL; 10156 - } 10157 10127 10158 10128 if (kvm_caps.has_tsc_control) { 10159 10129 /*
+2
arch/x86/kvm/x86.h
··· 471 471 472 472 extern bool enable_pmu; 473 473 474 + void kvm_setup_xss_caps(void); 475 + 474 476 /* 475 477 * Get a filtered version of KVM's supported XCR0 that strips out dynamic 476 478 * features for which the current process doesn't (yet) have permission to use.