* [PATCH 1/9] KVM: x86: nSVM: leave nested mode on vCPU free
[not found] <20221103135736.42295-1-mlevitsk@redhat.com>
@ 2022-11-03 13:57 ` Maxim Levitsky
2022-11-03 13:57 ` [PATCH 2/9] KVM: x86: nSVM: harden svm_free_nested against freeing vmcb02 while still in use Maxim Levitsky
` (3 subsequent siblings)
4 siblings, 0 replies; 5+ messages in thread
From: Maxim Levitsky @ 2022-11-03 13:57 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, H. Peter Anvin, Shuah Khan, Yang Zhong, Wei Wang,
Colton Lewis, Sean Christopherson, Jim Mattson, Chenyi Qiang,
Borislav Petkov, linux-kernel, x86, Thomas Gleixner, Dave Hansen,
Ingo Molnar, David Matlack, Peter Xu, Maxim Levitsky,
linux-kselftest, stable
If the VM was terminated while nested, we free the nested state
while the vCPU still is in nested mode.
Soon a warning will be added for this condition.
Cc: stable@vger.kernel.org
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
---
arch/x86/kvm/svm/svm.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index d22a809d923339..e9cec1b692051c 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -1440,6 +1440,7 @@ static void svm_vcpu_free(struct kvm_vcpu *vcpu)
*/
svm_clear_current_vmcb(svm->vmcb);
+ svm_leave_nested(vcpu);
svm_free_nested(svm);
sev_free_vcpu(vcpu);
--
2.34.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/9] KVM: x86: nSVM: harden svm_free_nested against freeing vmcb02 while still in use
[not found] <20221103135736.42295-1-mlevitsk@redhat.com>
2022-11-03 13:57 ` [PATCH 1/9] KVM: x86: nSVM: leave nested mode on vCPU free Maxim Levitsky
@ 2022-11-03 13:57 ` Maxim Levitsky
2022-11-03 13:57 ` [PATCH 3/9] KVM: x86: add kvm_leave_nested Maxim Levitsky
` (2 subsequent siblings)
4 siblings, 0 replies; 5+ messages in thread
From: Maxim Levitsky @ 2022-11-03 13:57 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, H. Peter Anvin, Shuah Khan, Yang Zhong, Wei Wang,
Colton Lewis, Sean Christopherson, Jim Mattson, Chenyi Qiang,
Borislav Petkov, linux-kernel, x86, Thomas Gleixner, Dave Hansen,
Ingo Molnar, David Matlack, Peter Xu, Maxim Levitsky,
linux-kselftest, stable
Make sure that KVM uses vmcb01 before freeing nested state, and warn if
that is not the case.
This is a minimal fix for CVE-2022-3344 making the kernel print a warning
instead of a kernel panic.
Cc: stable@vger.kernel.org
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
---
arch/x86/kvm/svm/nested.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index b258d6988f5dde..b74da40c1fc40c 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -1126,6 +1126,9 @@ void svm_free_nested(struct vcpu_svm *svm)
if (!svm->nested.initialized)
return;
+ if (WARN_ON_ONCE(svm->vmcb != svm->vmcb01.ptr))
+ svm_switch_vmcb(svm, &svm->vmcb01);
+
svm_vcpu_free_msrpm(svm->nested.msrpm);
svm->nested.msrpm = NULL;
--
2.34.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/9] KVM: x86: add kvm_leave_nested
[not found] <20221103135736.42295-1-mlevitsk@redhat.com>
2022-11-03 13:57 ` [PATCH 1/9] KVM: x86: nSVM: leave nested mode on vCPU free Maxim Levitsky
2022-11-03 13:57 ` [PATCH 2/9] KVM: x86: nSVM: harden svm_free_nested against freeing vmcb02 while still in use Maxim Levitsky
@ 2022-11-03 13:57 ` Maxim Levitsky
2022-11-03 13:57 ` [PATCH 4/9] KVM: x86: forcibly leave nested mode on vCPU reset Maxim Levitsky
2022-11-03 13:57 ` [PATCH 9/9] KVM: x86: remove exit_int_info warning in svm_handle_exit Maxim Levitsky
4 siblings, 0 replies; 5+ messages in thread
From: Maxim Levitsky @ 2022-11-03 13:57 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, H. Peter Anvin, Shuah Khan, Yang Zhong, Wei Wang,
Colton Lewis, Sean Christopherson, Jim Mattson, Chenyi Qiang,
Borislav Petkov, linux-kernel, x86, Thomas Gleixner, Dave Hansen,
Ingo Molnar, David Matlack, Peter Xu, Maxim Levitsky,
linux-kselftest, stable
add kvm_leave_nested which wraps a call to nested_ops->leave_nested
into a function.
Cc: stable@vger.kernel.org
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
---
arch/x86/kvm/svm/nested.c | 3 ---
arch/x86/kvm/vmx/nested.c | 3 ---
arch/x86/kvm/x86.c | 8 +++++++-
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index b74da40c1fc40c..bcc4f6620f8aec 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -1147,9 +1147,6 @@ void svm_free_nested(struct vcpu_svm *svm)
svm->nested.initialized = false;
}
-/*
- * Forcibly leave nested mode in order to be able to reset the VCPU later on.
- */
void svm_leave_nested(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 61a2e551640a08..1ebe141a0a015f 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -6441,9 +6441,6 @@ static int vmx_get_nested_state(struct kvm_vcpu *vcpu,
return kvm_state.size;
}
-/*
- * Forcibly leave nested mode in order to be able to reset the VCPU later on.
- */
void vmx_leave_nested(struct kvm_vcpu *vcpu)
{
if (is_guest_mode(vcpu)) {
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index cd9eb13e2ed7fc..316ab1d5317f92 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -627,6 +627,12 @@ static void kvm_queue_exception_vmexit(struct kvm_vcpu *vcpu, unsigned int vecto
ex->payload = payload;
}
+/* Forcibly leave the nested mode in cases like a vCPU reset */
+static void kvm_leave_nested(struct kvm_vcpu *vcpu)
+{
+ kvm_x86_ops.nested_ops->leave_nested(vcpu);
+}
+
static void kvm_multiple_exception(struct kvm_vcpu *vcpu,
unsigned nr, bool has_error, u32 error_code,
bool has_payload, unsigned long payload, bool reinject)
@@ -5193,7 +5199,7 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
if (events->flags & KVM_VCPUEVENT_VALID_SMM) {
#ifdef CONFIG_KVM_SMM
if (!!(vcpu->arch.hflags & HF_SMM_MASK) != events->smi.smm) {
- kvm_x86_ops.nested_ops->leave_nested(vcpu);
+ kvm_leave_nested(vcpu);
kvm_smm_changed(vcpu, events->smi.smm);
}
--
2.34.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 4/9] KVM: x86: forcibly leave nested mode on vCPU reset
[not found] <20221103135736.42295-1-mlevitsk@redhat.com>
` (2 preceding siblings ...)
2022-11-03 13:57 ` [PATCH 3/9] KVM: x86: add kvm_leave_nested Maxim Levitsky
@ 2022-11-03 13:57 ` Maxim Levitsky
2022-11-03 13:57 ` [PATCH 9/9] KVM: x86: remove exit_int_info warning in svm_handle_exit Maxim Levitsky
4 siblings, 0 replies; 5+ messages in thread
From: Maxim Levitsky @ 2022-11-03 13:57 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, H. Peter Anvin, Shuah Khan, Yang Zhong, Wei Wang,
Colton Lewis, Sean Christopherson, Jim Mattson, Chenyi Qiang,
Borislav Petkov, linux-kernel, x86, Thomas Gleixner, Dave Hansen,
Ingo Molnar, David Matlack, Peter Xu, Maxim Levitsky,
linux-kselftest, stable
While not obivous, kvm_vcpu_reset() leaves the nested mode by clearing
'vcpu->arch.hflags' but it does so without all the required housekeeping.
On SVM, it is possible to have a vCPU reset while in guest mode because
unlike VMX, on SVM, INIT's are not latched in SVM non root mode and in
addition to that L1 doesn't have to intercept triple fault, which should
also trigger L1's reset if happens in L2 while L1 didn't intercept it.
If one of the above conditions happen, KVM will continue to use vmcb02 while
not having in the guest mode.
Later the IA32_EFER will be cleared which will lead to freeing of the nested
guest state which will (correctly) free the vmcb02, but since KVM still
uses it (incorrectly) this will lead to a use after free and kernel crash.
This issue is assigned CVE-2022-3344
Cc: stable@vger.kernel.org
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
---
arch/x86/kvm/x86.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 316ab1d5317f92..3fd900504e683b 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -11694,8 +11694,18 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
WARN_ON_ONCE(!init_event &&
(old_cr0 || kvm_read_cr3(vcpu) || kvm_read_cr4(vcpu)));
+ /*
+ * SVM doesn't unconditionally VM-Exit on INIT and SHUTDOWN, thus it's
+ * possible to INIT the vCPU while L2 is active. Force the vCPU back
+ * into L1 as EFER.SVME is cleared on INIT (along with all other EFER
+ * bits), i.e. virtualization is disabled.
+ */
+ if (is_guest_mode(vcpu))
+ kvm_leave_nested(vcpu);
+
kvm_lapic_reset(vcpu, init_event);
+ WARN_ON_ONCE(is_guest_mode(vcpu) || is_smm(vcpu));
vcpu->arch.hflags = 0;
vcpu->arch.smi_pending = 0;
--
2.34.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 9/9] KVM: x86: remove exit_int_info warning in svm_handle_exit
[not found] <20221103135736.42295-1-mlevitsk@redhat.com>
` (3 preceding siblings ...)
2022-11-03 13:57 ` [PATCH 4/9] KVM: x86: forcibly leave nested mode on vCPU reset Maxim Levitsky
@ 2022-11-03 13:57 ` Maxim Levitsky
4 siblings, 0 replies; 5+ messages in thread
From: Maxim Levitsky @ 2022-11-03 13:57 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, H. Peter Anvin, Shuah Khan, Yang Zhong, Wei Wang,
Colton Lewis, Sean Christopherson, Jim Mattson, Chenyi Qiang,
Borislav Petkov, linux-kernel, x86, Thomas Gleixner, Dave Hansen,
Ingo Molnar, David Matlack, Peter Xu, Maxim Levitsky,
linux-kselftest, stable
It is valid to receive external interrupt and have broken IDT entry,
which will lead to #GP with exit_int_into that will contain the index of
the IDT entry (e.g any value).
Other exceptions can happen as well, like #NP or #SS
(if stack switch fails).
Thus this warning can be user triggred and has very little value.
Cc: stable@vger.kernel.org
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
---
arch/x86/kvm/svm/svm.c | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index e9cec1b692051c..36f651ce842174 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3428,15 +3428,6 @@ static int svm_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
return 0;
}
- if (is_external_interrupt(svm->vmcb->control.exit_int_info) &&
- exit_code != SVM_EXIT_EXCP_BASE + PF_VECTOR &&
- exit_code != SVM_EXIT_NPF && exit_code != SVM_EXIT_TASK_SWITCH &&
- exit_code != SVM_EXIT_INTR && exit_code != SVM_EXIT_NMI)
- printk(KERN_ERR "%s: unexpected exit_int_info 0x%x "
- "exit_code 0x%x\n",
- __func__, svm->vmcb->control.exit_int_info,
- exit_code);
-
if (exit_fastpath != EXIT_FASTPATH_NONE)
return 1;
--
2.34.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2022-11-03 14:00 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20221103135736.42295-1-mlevitsk@redhat.com>
2022-11-03 13:57 ` [PATCH 1/9] KVM: x86: nSVM: leave nested mode on vCPU free Maxim Levitsky
2022-11-03 13:57 ` [PATCH 2/9] KVM: x86: nSVM: harden svm_free_nested against freeing vmcb02 while still in use Maxim Levitsky
2022-11-03 13:57 ` [PATCH 3/9] KVM: x86: add kvm_leave_nested Maxim Levitsky
2022-11-03 13:57 ` [PATCH 4/9] KVM: x86: forcibly leave nested mode on vCPU reset Maxim Levitsky
2022-11-03 13:57 ` [PATCH 9/9] KVM: x86: remove exit_int_info warning in svm_handle_exit Maxim Levitsky
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).