All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/5] KVM: x86: Fix EFER reserved bits initialization
@ 2026-07-13 18:10 Yosry Ahmed
  2026-07-13 18:10 ` [PATCH v3 1/5] KVM: x86: Move enabling EFER.SVME and EFER.LMSLE to generic EFER setup Yosry Ahmed
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Yosry Ahmed @ 2026-07-13 18:10 UTC (permalink / raw)
  To: Sean Christopherson; +Cc: Paolo Bonzini, kvm, linux-kernel, Yosry Ahmed

v3 of fixing EFER reserved bits initialization on vendor module reload,
and move them into kvm_caps. I reworked and reordered the patches such
that we go straight to reinitializing the EFER reserved bits, instead of
first re-reserving the bits on vendor init if nested=0.

The motivation for the previous approach was simpler backports, but
practically the fixes don't apply cleanly anyway to most stable kernels
due to EFER.LMSLE handling being introduced very recently.

v2 -> v3:
- Drop KVM_SET_SREGS* validity checks fixes, sent separately.
- Re-ordered and reworked the patches to re-initialize EFER reserved
  bits right away.
- Drop the per-vendor op for EFER caps initialization, instead move
  EFER.SVME and EFER.LMSLE handling to generic x86 code.

Yosry Ahmed (5):
  KVM: x86: Move enabling EFER.SVME and EFER.LMSLE to generic EFER setup
  KVM: x86: Disallow EFER.LME and EFER.LMA if long mode is not supported
  KVM: x86: Always initialize EFER reserved bits on vendor
    initialization
  KVM: x86: Reverse the polarity of efer_reserved_bits
  KVM: x86: Move supported EFER bits to kvm_caps

 arch/x86/include/asm/kvm_host.h |  2 ++
 arch/x86/kvm/msrs.c             | 21 ++-------------------
 arch/x86/kvm/msrs.h             |  1 -
 arch/x86/kvm/svm/svm.c          |  4 ----
 arch/x86/kvm/x86.c              | 18 +++++++++++++++---
 5 files changed, 19 insertions(+), 27 deletions(-)


base-commit: 3aec122bdcaf6f8c4ecfc7f6adf6773015ced676
-- 
2.55.0.141.g00534a21ce-goog


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v3 1/5] KVM: x86: Move enabling EFER.SVME and EFER.LMSLE to generic EFER setup
  2026-07-13 18:10 [PATCH v3 0/5] KVM: x86: Fix EFER reserved bits initialization Yosry Ahmed
@ 2026-07-13 18:10 ` Yosry Ahmed
  2026-07-13 18:10 ` [PATCH v3 2/5] KVM: x86: Disallow EFER.LME and EFER.LMA if long mode is not supported Yosry Ahmed
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Yosry Ahmed @ 2026-07-13 18:10 UTC (permalink / raw)
  To: Sean Christopherson; +Cc: Paolo Bonzini, kvm, linux-kernel, Yosry Ahmed, stable

Move SVM-specific EFER bit enablement to generic x86 code, with the rest
of EFER bit enablement. Unifying the code for EFER bit enablement allows
for a later change to re-initialize EFER bits on module init.

No functional change intended.

Cc: stable@vger.kernel.org
Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Yosry Ahmed <yosry@kernel.org>
---
 arch/x86/kvm/svm/svm.c | 4 ----
 arch/x86/kvm/x86.c     | 6 ++++++
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 91286d46d13ad..09799fd8ef38f 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -5628,10 +5628,6 @@ static __init int svm_hardware_setup(void)
 
 	if (nested) {
 		pr_info("Nested Virtualization enabled\n");
-		kvm_enable_efer_bits(EFER_SVME);
-		if (!boot_cpu_has(X86_FEATURE_EFER_LMSLE_MBZ))
-			kvm_enable_efer_bits(EFER_LMSLE);
-
 		r = nested_svm_init_msrpm_merge_offsets();
 		if (r)
 			return r;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 1f5dc685f0490..ca01a2f2ec466 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6921,6 +6921,12 @@ static void kvm_setup_efer_caps(void)
 
 	if (kvm_cpu_cap_has(X86_FEATURE_AUTOIBRS))
 		kvm_enable_efer_bits(EFER_AUTOIBRS);
+
+	if (kvm_cpu_cap_has(X86_FEATURE_SVM)) {
+		kvm_enable_efer_bits(EFER_SVME);
+		if (!boot_cpu_has(X86_FEATURE_EFER_LMSLE_MBZ))
+			kvm_enable_efer_bits(EFER_LMSLE);
+	}
 }
 
 static void kvm_nested_ops_update(const struct kvm_x86_nested_ops *nested_ops)
-- 
2.55.0.141.g00534a21ce-goog


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 2/5] KVM: x86: Disallow EFER.LME and EFER.LMA if long mode is not supported
  2026-07-13 18:10 [PATCH v3 0/5] KVM: x86: Fix EFER reserved bits initialization Yosry Ahmed
  2026-07-13 18:10 ` [PATCH v3 1/5] KVM: x86: Move enabling EFER.SVME and EFER.LMSLE to generic EFER setup Yosry Ahmed
@ 2026-07-13 18:10 ` Yosry Ahmed
  2026-07-13 18:42   ` sashiko-bot
  2026-07-13 18:10 ` [PATCH v3 3/5] KVM: x86: Always initialize EFER reserved bits on vendor initialization Yosry Ahmed
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Yosry Ahmed @ 2026-07-13 18:10 UTC (permalink / raw)
  To: Sean Christopherson; +Cc: Paolo Bonzini, kvm, linux-kernel, Yosry Ahmed, stable

Remove EFER.LME and EFER.LMA from EFER reserved bits only if long mode
is actually supported. KVM does check long-mode support before allowing
the bits for guest writes and userspace writes through KVM_SET_SREGS*
(in __kvm_valid_efer()), but userspace writes through KVM_SET_MSRS only
check reserved bits.

In practice, this doesn't really matter. The true motiviation is getting
rid of the #ifdeffery when initializing efer_reserved_bits.

Cc: stable@vger.kernel.org
Signed-off-by: Yosry Ahmed <yosry@kernel.org>
---
 arch/x86/kvm/msrs.c | 10 +---------
 arch/x86/kvm/x86.c  |  3 +++
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/arch/x86/kvm/msrs.c b/arch/x86/kvm/msrs.c
index c230b18d87e38..67481429ad6b8 100644
--- a/arch/x86/kvm/msrs.c
+++ b/arch/x86/kvm/msrs.c
@@ -19,16 +19,8 @@ bool __read_mostly report_ignored_msrs = true;
 module_param(report_ignored_msrs, bool, 0644);
 EXPORT_SYMBOL_FOR_KVM_INTERNAL(report_ignored_msrs);
 
-/* EFER defaults:
- * - enable syscall per default because its emulated by KVM
- * - enable LME and LMA per default on 64 bit KVM
- */
-#ifdef CONFIG_X86_64
-static
-u64 __read_mostly efer_reserved_bits = ~((u64)(EFER_SCE | EFER_LME | EFER_LMA));
-#else
+/* Enable syscall by default because its emulated by KVM */
 static u64 __read_mostly efer_reserved_bits = ~((u64)EFER_SCE);
-#endif
 
 #define MAX_IO_MSRS 256
 
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index ca01a2f2ec466..f68424a985cda 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6913,6 +6913,9 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_setup_xss_caps);
 
 static void kvm_setup_efer_caps(void)
 {
+	if (kvm_cpu_cap_has(X86_FEATURE_LM))
+		kvm_enable_efer_bits(EFER_LME | EFER_LMA);
+
 	if (kvm_cpu_cap_has(X86_FEATURE_NX))
 		kvm_enable_efer_bits(EFER_NX);
 
-- 
2.55.0.141.g00534a21ce-goog


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 3/5] KVM: x86: Always initialize EFER reserved bits on vendor initialization
  2026-07-13 18:10 [PATCH v3 0/5] KVM: x86: Fix EFER reserved bits initialization Yosry Ahmed
  2026-07-13 18:10 ` [PATCH v3 1/5] KVM: x86: Move enabling EFER.SVME and EFER.LMSLE to generic EFER setup Yosry Ahmed
  2026-07-13 18:10 ` [PATCH v3 2/5] KVM: x86: Disallow EFER.LME and EFER.LMA if long mode is not supported Yosry Ahmed
@ 2026-07-13 18:10 ` Yosry Ahmed
  2026-07-13 18:10 ` [PATCH v3 4/5] KVM: x86: Reverse the polarity of efer_reserved_bits Yosry Ahmed
  2026-07-13 18:10 ` [PATCH v3 5/5] KVM: x86: Move supported EFER bits to kvm_caps Yosry Ahmed
  4 siblings, 0 replies; 8+ messages in thread
From: Yosry Ahmed @ 2026-07-13 18:10 UTC (permalink / raw)
  To: Sean Christopherson; +Cc: Paolo Bonzini, kvm, linux-kernel, Yosry Ahmed, stable

EFER reserved bits are statically initialized, and do not reset if a
vendor module is re-loaded. For example, loading kvm_amd with nested=1
removes EFER.SVME (and potentially EFER.LMSLE) from the reserved bits.
Reloading kvm_amd with nested=0 does not add them back, allowing
userspace to set EFER.SVME with nested=0.

Re-initializing EFER reserved bits before configuring them on vendor
initialization.

Cc: stable@vger.kernel.org
Signed-off-by: Yosry Ahmed <yosry@kernel.org>
---
 arch/x86/kvm/msrs.c | 10 ++++++++--
 arch/x86/kvm/msrs.h |  1 +
 arch/x86/kvm/x86.c  |  2 ++
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/msrs.c b/arch/x86/kvm/msrs.c
index 67481429ad6b8..a7394bdae0295 100644
--- a/arch/x86/kvm/msrs.c
+++ b/arch/x86/kvm/msrs.c
@@ -19,8 +19,7 @@ bool __read_mostly report_ignored_msrs = true;
 module_param(report_ignored_msrs, bool, 0644);
 EXPORT_SYMBOL_FOR_KVM_INTERNAL(report_ignored_msrs);
 
-/* Enable syscall by default because its emulated by KVM */
-static u64 __read_mostly efer_reserved_bits = ~((u64)EFER_SCE);
+static u64 __read_mostly efer_reserved_bits;
 
 #define MAX_IO_MSRS 256
 
@@ -650,6 +649,13 @@ static int set_efer(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 	return 0;
 }
 
+void kvm_init_efer_bits(void)
+{
+	/* Enable syscall by default because its emulated by KVM */
+	efer_reserved_bits = ~((u64)EFER_SCE);
+}
+EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_init_efer_bits);
+
 void kvm_enable_efer_bits(u64 mask)
 {
        efer_reserved_bits &= ~mask;
diff --git a/arch/x86/kvm/msrs.h b/arch/x86/kvm/msrs.h
index 9c5c6b33e58f5..1f772e1717588 100644
--- a/arch/x86/kvm/msrs.h
+++ b/arch/x86/kvm/msrs.h
@@ -58,6 +58,7 @@ int kvm_get_set_one_reg(struct kvm_vcpu *vcpu, unsigned int ioctl,
 int kvm_get_reg_list(struct kvm_vcpu *vcpu,
 		     struct kvm_reg_list __user *user_list);
 
+void kvm_init_efer_bits(void);
 void kvm_enable_efer_bits(u64);
 bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer);
 int kvm_emulate_msr_read(struct kvm_vcpu *vcpu, u32 index, u64 *data);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index f68424a985cda..83f608dad0605 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6913,6 +6913,8 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_setup_xss_caps);
 
 static void kvm_setup_efer_caps(void)
 {
+	kvm_init_efer_bits();
+
 	if (kvm_cpu_cap_has(X86_FEATURE_LM))
 		kvm_enable_efer_bits(EFER_LME | EFER_LMA);
 
-- 
2.55.0.141.g00534a21ce-goog


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 4/5] KVM: x86: Reverse the polarity of efer_reserved_bits
  2026-07-13 18:10 [PATCH v3 0/5] KVM: x86: Fix EFER reserved bits initialization Yosry Ahmed
                   ` (2 preceding siblings ...)
  2026-07-13 18:10 ` [PATCH v3 3/5] KVM: x86: Always initialize EFER reserved bits on vendor initialization Yosry Ahmed
@ 2026-07-13 18:10 ` Yosry Ahmed
  2026-07-13 18:10 ` [PATCH v3 5/5] KVM: x86: Move supported EFER bits to kvm_caps Yosry Ahmed
  4 siblings, 0 replies; 8+ messages in thread
From: Yosry Ahmed @ 2026-07-13 18:10 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Paolo Bonzini, kvm, linux-kernel, Yosry Ahmed, Nikolay Borisov

In preparation for moving efer_reserved_bits into kvm_caps, reverse its
polarity and make it efer_supported_bits, to be more consistent with
other fields in kvm_caps.

No functional change intended.

Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Signed-off-by: Yosry Ahmed <yosry@kernel.org>
---
 arch/x86/kvm/msrs.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kvm/msrs.c b/arch/x86/kvm/msrs.c
index a7394bdae0295..8e33b87b5e8f0 100644
--- a/arch/x86/kvm/msrs.c
+++ b/arch/x86/kvm/msrs.c
@@ -19,7 +19,7 @@ bool __read_mostly report_ignored_msrs = true;
 module_param(report_ignored_msrs, bool, 0644);
 EXPORT_SYMBOL_FOR_KVM_INTERNAL(report_ignored_msrs);
 
-static u64 __read_mostly efer_reserved_bits;
+static u64 __read_mostly efer_supported_bits;
 
 #define MAX_IO_MSRS 256
 
@@ -605,7 +605,7 @@ static bool __kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer)
 }
 bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer)
 {
-	if (efer & efer_reserved_bits)
+	if (efer & ~efer_supported_bits)
 		return false;
 
 	return __kvm_valid_efer(vcpu, efer);
@@ -618,7 +618,7 @@ static int set_efer(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 	u64 efer = msr_info->data;
 	int r;
 
-	if (efer & efer_reserved_bits)
+	if (efer & ~efer_supported_bits)
 		return 1;
 
 	if (!msr_info->host_initiated) {
@@ -652,13 +652,13 @@ static int set_efer(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 void kvm_init_efer_bits(void)
 {
 	/* Enable syscall by default because its emulated by KVM */
-	efer_reserved_bits = ~((u64)EFER_SCE);
+	efer_supported_bits = (u64)EFER_SCE;
 }
 EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_init_efer_bits);
 
 void kvm_enable_efer_bits(u64 mask)
 {
-       efer_reserved_bits &= ~mask;
+	efer_supported_bits |= mask;
 }
 EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_enable_efer_bits);
 
-- 
2.55.0.141.g00534a21ce-goog


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 5/5] KVM: x86: Move supported EFER bits to kvm_caps
  2026-07-13 18:10 [PATCH v3 0/5] KVM: x86: Fix EFER reserved bits initialization Yosry Ahmed
                   ` (3 preceding siblings ...)
  2026-07-13 18:10 ` [PATCH v3 4/5] KVM: x86: Reverse the polarity of efer_reserved_bits Yosry Ahmed
@ 2026-07-13 18:10 ` Yosry Ahmed
  4 siblings, 0 replies; 8+ messages in thread
From: Yosry Ahmed @ 2026-07-13 18:10 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Paolo Bonzini, kvm, linux-kernel, Yosry Ahmed, Nikolay Borisov

Supported EFER bits naturally fits into kvm_caps because it gets
recomputed during vendor initialization (e.g. to account for EFER.SVME
being allowed/disallowed based on nested being enabled/disabled). Move
efer_supported_bits into kvm_caps as supported_efer_bits (for naming
consistency).

As the bitmask is now globally visible as part of kvm_caps, there's
little use for helpers to enable/disable specific bits, so drop them and
open-code updates to kvm_caps.supported_efer_bits.

No functional change intended.

Suggested-by: Sean Christopherson <seanjc@google.com>
Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Signed-off-by: Yosry Ahmed <yosry@kernel.org>
---
 arch/x86/include/asm/kvm_host.h |  2 ++
 arch/x86/kvm/msrs.c             | 19 ++-----------------
 arch/x86/kvm/msrs.h             |  2 --
 arch/x86/kvm/x86.c              | 15 ++++++++-------
 4 files changed, 12 insertions(+), 26 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 58f156ae31e75..80b92ed440fa1 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -274,6 +274,8 @@ struct kvm_caps {
 	u64 supported_xss;
 	u64 supported_perf_cap;
 
+	u64 supported_efer_bits;
+
 	u64 supported_quirks;
 	u64 inapplicable_quirks;
 };
diff --git a/arch/x86/kvm/msrs.c b/arch/x86/kvm/msrs.c
index 8e33b87b5e8f0..66fa7140d65d9 100644
--- a/arch/x86/kvm/msrs.c
+++ b/arch/x86/kvm/msrs.c
@@ -19,8 +19,6 @@ bool __read_mostly report_ignored_msrs = true;
 module_param(report_ignored_msrs, bool, 0644);
 EXPORT_SYMBOL_FOR_KVM_INTERNAL(report_ignored_msrs);
 
-static u64 __read_mostly efer_supported_bits;
-
 #define MAX_IO_MSRS 256
 
 struct msr_bitmap_range {
@@ -605,7 +603,7 @@ static bool __kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer)
 }
 bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer)
 {
-	if (efer & ~efer_supported_bits)
+	if (efer & ~kvm_caps.supported_efer_bits)
 		return false;
 
 	return __kvm_valid_efer(vcpu, efer);
@@ -618,7 +616,7 @@ static int set_efer(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 	u64 efer = msr_info->data;
 	int r;
 
-	if (efer & ~efer_supported_bits)
+	if (efer & ~kvm_caps.supported_efer_bits)
 		return 1;
 
 	if (!msr_info->host_initiated) {
@@ -649,19 +647,6 @@ static int set_efer(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 	return 0;
 }
 
-void kvm_init_efer_bits(void)
-{
-	/* Enable syscall by default because its emulated by KVM */
-	efer_supported_bits = (u64)EFER_SCE;
-}
-EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_init_efer_bits);
-
-void kvm_enable_efer_bits(u64 mask)
-{
-	efer_supported_bits |= mask;
-}
-EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_enable_efer_bits);
-
 bool kvm_msr_allowed(struct kvm_vcpu *vcpu, u32 index, u32 type)
 {
 	struct kvm_x86_msr_filter *msr_filter;
diff --git a/arch/x86/kvm/msrs.h b/arch/x86/kvm/msrs.h
index 1f772e1717588..7cc182a15b3b3 100644
--- a/arch/x86/kvm/msrs.h
+++ b/arch/x86/kvm/msrs.h
@@ -58,8 +58,6 @@ int kvm_get_set_one_reg(struct kvm_vcpu *vcpu, unsigned int ioctl,
 int kvm_get_reg_list(struct kvm_vcpu *vcpu,
 		     struct kvm_reg_list __user *user_list);
 
-void kvm_init_efer_bits(void);
-void kvm_enable_efer_bits(u64);
 bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer);
 int kvm_emulate_msr_read(struct kvm_vcpu *vcpu, u32 index, u64 *data);
 int kvm_emulate_msr_write(struct kvm_vcpu *vcpu, u32 index, u64 data);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 83f608dad0605..a020b1cbb3f3e 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6913,24 +6913,25 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_setup_xss_caps);
 
 static void kvm_setup_efer_caps(void)
 {
-	kvm_init_efer_bits();
+	/* Enable syscall by default because its emulated by KVM */
+	kvm_caps.supported_efer_bits = (u64)EFER_SCE;
 
 	if (kvm_cpu_cap_has(X86_FEATURE_LM))
-		kvm_enable_efer_bits(EFER_LME | EFER_LMA);
+		kvm_caps.supported_efer_bits |= (EFER_LME | EFER_LMA);
 
 	if (kvm_cpu_cap_has(X86_FEATURE_NX))
-		kvm_enable_efer_bits(EFER_NX);
+		kvm_caps.supported_efer_bits |= EFER_NX;
 
 	if (kvm_cpu_cap_has(X86_FEATURE_FXSR_OPT))
-		kvm_enable_efer_bits(EFER_FFXSR);
+		kvm_caps.supported_efer_bits |= EFER_FFXSR;
 
 	if (kvm_cpu_cap_has(X86_FEATURE_AUTOIBRS))
-		kvm_enable_efer_bits(EFER_AUTOIBRS);
+		kvm_caps.supported_efer_bits |= EFER_AUTOIBRS;
 
 	if (kvm_cpu_cap_has(X86_FEATURE_SVM)) {
-		kvm_enable_efer_bits(EFER_SVME);
+		kvm_caps.supported_efer_bits |= EFER_SVME;
 		if (!boot_cpu_has(X86_FEATURE_EFER_LMSLE_MBZ))
-			kvm_enable_efer_bits(EFER_LMSLE);
+			kvm_caps.supported_efer_bits |= EFER_LMSLE;
 	}
 }
 
-- 
2.55.0.141.g00534a21ce-goog


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 2/5] KVM: x86: Disallow EFER.LME and EFER.LMA if long mode is not supported
  2026-07-13 18:10 ` [PATCH v3 2/5] KVM: x86: Disallow EFER.LME and EFER.LMA if long mode is not supported Yosry Ahmed
@ 2026-07-13 18:42   ` sashiko-bot
  2026-07-13 18:50     ` Yosry Ahmed
  0 siblings, 1 reply; 8+ messages in thread
From: sashiko-bot @ 2026-07-13 18:42 UTC (permalink / raw)
  To: Yosry Ahmed; +Cc: kvm

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] KVM_SET_SREGS bypasses EFER validation, permitting userspace to set unsupported EFER bits and potentially triggering a host kernel BUG_ON.
--

--- Patch [2]: [PATCH v3 2/5] KVM: x86: Disallow EFER.LME and EFER.LMA if long mode is not supported ---
commit 804513f9cd9e8710ae3f651192ce52e48ee9e59a
Author: Yosry Ahmed <yosry@kernel.org>

KVM: x86: Disallow EFER.LME and EFER.LMA if long mode is not supported

Remove EFER.LME and EFER.LMA from EFER reserved bits only if long mode
is actually supported.

> KVM does check long-mode support before allowing
> the bits for guest writes and userspace writes through KVM_SET_SREGS*
> (in __kvm_valid_efer()), but userspace writes through KVM_SET_MSRS only
> check reserved bits.

[Severity: High]
This isn't a bug introduced by this patch, but is the claim about
KVM_SET_SREGS* checking __kvm_valid_efer() accurate?

It looks like KVM_SET_SREGS can actually bypass __kvm_valid_efer(). If
userspace invokes the KVM_SET_SREGS ioctl with a crafted sregs structure
where EFER_LME=1, EFER_LMA=1, CR0.PG=1, and CR4.PAE=1, this state appears
to bypass the consistency checks in kvm_is_valid_sregs().

Then, __set_sregs_common() applies the EFER bits directly via the
architecture-specific callback:

arch/x86/kvm/regs.c:__set_sregs_common() {
    ...
    kvm_x86_call(set_efer)(vcpu, sregs->efer);
    ...
}

On a 32-bit KVM host (!CONFIG_X86_64), this call reaches vmx_set_efer(),
which unconditionally triggers a KVM_BUG_ON since long mode is not
supported:

arch/x86/kvm/vmx/vmx.c:vmx_set_efer() {
    ...
    if (KVM_BUG_ON(efer & EFER_LMA, vcpu->kvm))
        return 1;
    ...
}

Additionally, on SVM, bypassing __kvm_valid_efer() allows userspace to set
EFER_SVME and force nested state allocation even when the guest lacks the
X86_FEATURE_SVM capability.

Could this allow a malicious unprivileged userspace process to trigger a
host kernel panic (if panic_on_warn=1) by forcing this KVM_BUG_ON?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260713181020.2735367-1-yosry@kernel.org?part=2

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 2/5] KVM: x86: Disallow EFER.LME and EFER.LMA if long mode is not supported
  2026-07-13 18:42   ` sashiko-bot
@ 2026-07-13 18:50     ` Yosry Ahmed
  0 siblings, 0 replies; 8+ messages in thread
From: Yosry Ahmed @ 2026-07-13 18:50 UTC (permalink / raw)
  To: sashiko-reviews; +Cc: kvm

On Mon, Jul 13, 2026 at 11:42 AM <sashiko-bot@kernel.org> wrote:
>
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>
> Pre-existing issues:
> - [High] KVM_SET_SREGS bypasses EFER validation, permitting userspace to set unsupported EFER bits and potentially triggering a host kernel BUG_ON.
> --
>
> --- Patch [2]: [PATCH v3 2/5] KVM: x86: Disallow EFER.LME and EFER.LMA if long mode is not supported ---
> commit 804513f9cd9e8710ae3f651192ce52e48ee9e59a
> Author: Yosry Ahmed <yosry@kernel.org>
>
> KVM: x86: Disallow EFER.LME and EFER.LMA if long mode is not supported
>
> Remove EFER.LME and EFER.LMA from EFER reserved bits only if long mode
> is actually supported.
>
> > KVM does check long-mode support before allowing
> > the bits for guest writes and userspace writes through KVM_SET_SREGS*
> > (in __kvm_valid_efer()), but userspace writes through KVM_SET_MSRS only
> > check reserved bits.
>
> [Severity: High]
> This isn't a bug introduced by this patch, but is the claim about
> KVM_SET_SREGS* checking __kvm_valid_efer() accurate?
>
> It looks like KVM_SET_SREGS can actually bypass __kvm_valid_efer(). If
> userspace invokes the KVM_SET_SREGS ioctl with a crafted sregs structure
> where EFER_LME=1, EFER_LMA=1, CR0.PG=1, and CR4.PAE=1, this state appears
> to bypass the consistency checks in kvm_is_valid_sregs().

This is fixed by
https://lore.kernel.org/kvm/20260713181413.94A481F00A3D@smtp.kernel.org/.
I forgot to update the changelog here after I split the series.

>
> Then, __set_sregs_common() applies the EFER bits directly via the
> architecture-specific callback:
>
> arch/x86/kvm/regs.c:__set_sregs_common() {
>     ...
>     kvm_x86_call(set_efer)(vcpu, sregs->efer);
>     ...
> }
>
> On a 32-bit KVM host (!CONFIG_X86_64), this call reaches vmx_set_efer(),
> which unconditionally triggers a KVM_BUG_ON since long mode is not
> supported:
>
> arch/x86/kvm/vmx/vmx.c:vmx_set_efer() {
>     ...
>     if (KVM_BUG_ON(efer & EFER_LMA, vcpu->kvm))
>         return 1;
>     ...
> }
>
> Additionally, on SVM, bypassing __kvm_valid_efer() allows userspace to set
> EFER_SVME and force nested state allocation even when the guest lacks the
> X86_FEATURE_SVM capability.
>
> Could this allow a malicious unprivileged userspace process to trigger a
> host kernel panic (if panic_on_warn=1) by forcing this KVM_BUG_ON?
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260713181020.2735367-1-yosry@kernel.org?part=2

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-07-13 18:50 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-13 18:10 [PATCH v3 0/5] KVM: x86: Fix EFER reserved bits initialization Yosry Ahmed
2026-07-13 18:10 ` [PATCH v3 1/5] KVM: x86: Move enabling EFER.SVME and EFER.LMSLE to generic EFER setup Yosry Ahmed
2026-07-13 18:10 ` [PATCH v3 2/5] KVM: x86: Disallow EFER.LME and EFER.LMA if long mode is not supported Yosry Ahmed
2026-07-13 18:42   ` sashiko-bot
2026-07-13 18:50     ` Yosry Ahmed
2026-07-13 18:10 ` [PATCH v3 3/5] KVM: x86: Always initialize EFER reserved bits on vendor initialization Yosry Ahmed
2026-07-13 18:10 ` [PATCH v3 4/5] KVM: x86: Reverse the polarity of efer_reserved_bits Yosry Ahmed
2026-07-13 18:10 ` [PATCH v3 5/5] KVM: x86: Move supported EFER bits to kvm_caps Yosry Ahmed

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.