From: Xiaoyao Li <xiaoyao.li@intel.com>
To: Paolo Bonzini <pbonzini@redhat.com>,
Sean Christopherson <sean.j.christopherson@intel.com>,
Jim Mattson <jmattson@google.com>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-doc@vger.kernel.org, Jonathan Corbet <corbet@lwn.net>,
Vitaly Kuznetsov <vkuznets@redhat.com>,
Wanpeng Li <wanpengli@tencent.com>,
Joerg Roedel <joro@8bytes.org>, Xiaoyao Li <xiaoyao.li@intel.com>
Subject: [PATCH v3 3/8] KVM: X86: Introduce kvm_check_cpuid()
Date: Wed, 8 Jul 2020 14:50:49 +0800 [thread overview]
Message-ID: <20200708065054.19713-4-xiaoyao.li@intel.com> (raw)
In-Reply-To: <20200708065054.19713-1-xiaoyao.li@intel.com>
Use kvm_check_cpuid() to validate if userspace provides legal cpuid
settings and call it before KVM updates CPUID.
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
---
Is the check of virutal address width really necessary?
KVM doesn't check other bits at all. I guess the policy is that KVM allows
illegal CPUID settings as long as it doesn't break host kernel. Userspace
takes the consequences itself if it sets bogus CPUID settings that breaks
its guest.
But why vaddr_bits is special? It seems illegal vaddr_bits won't break host
kernel.
---
arch/x86/kvm/cpuid.c | 54 ++++++++++++++++++++++++++++----------------
arch/x86/kvm/cpuid.h | 2 +-
2 files changed, 35 insertions(+), 21 deletions(-)
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 0e3a23c2ea55..a825878b7f84 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -54,7 +54,26 @@ static u32 xstate_required_size(u64 xstate_bv, bool compacted)
#define F feature_bit
-int kvm_update_cpuid(struct kvm_vcpu *vcpu)
+static int kvm_check_cpuid(struct kvm_vcpu *vcpu)
+{
+ struct kvm_cpuid_entry2 *best;
+
+ /*
+ * The existing code assumes virtual address is 48-bit or 57-bit in the
+ * canonical address checks; exit if it is ever changed.
+ */
+ best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
+ if (best) {
+ int vaddr_bits = (best->eax & 0xff00) >> 8;
+
+ if (vaddr_bits != 48 && vaddr_bits != 57 && vaddr_bits != 0)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void kvm_update_cpuid(struct kvm_vcpu *vcpu)
{
struct kvm_cpuid_entry2 *best;
struct kvm_lapic *apic = vcpu->arch.apic;
@@ -96,18 +115,6 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu)
cpuid_entry_has(best, X86_FEATURE_XSAVEC)))
best->ebx = xstate_required_size(vcpu->arch.xcr0, true);
- /*
- * The existing code assumes virtual address is 48-bit or 57-bit in the
- * canonical address checks; exit if it is ever changed.
- */
- best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
- if (best) {
- int vaddr_bits = (best->eax & 0xff00) >> 8;
-
- if (vaddr_bits != 48 && vaddr_bits != 57 && vaddr_bits != 0)
- return -EINVAL;
- }
-
best = kvm_find_cpuid_entry(vcpu, KVM_CPUID_FEATURES, 0);
if (kvm_hlt_in_guest(vcpu->kvm) && best &&
(best->eax & (1 << KVM_FEATURE_PV_UNHALT)))
@@ -127,7 +134,6 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu)
kvm_mmu_reset_context(vcpu);
kvm_pmu_refresh(vcpu);
- return 0;
}
static int is_efer_nx(void)
@@ -202,12 +208,16 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
vcpu->arch.cpuid_entries[i].padding[2] = 0;
}
vcpu->arch.cpuid_nent = cpuid->nent;
+ r = kvm_check_cpuid(vcpu);
+ if (r) {
+ vcpu->arch.cpuid_nent = 0;
+ goto out;
+ }
+
cpuid_fix_nx_cap(vcpu);
kvm_apic_set_version(vcpu);
kvm_x86_ops.cpuid_update(vcpu);
- r = kvm_update_cpuid(vcpu);
- if (r)
- vcpu->arch.cpuid_nent = 0;
+ kvm_update_cpuid(vcpu);
kvfree(cpuid_entries);
out:
@@ -228,11 +238,15 @@ int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu,
cpuid->nent * sizeof(struct kvm_cpuid_entry2)))
goto out;
vcpu->arch.cpuid_nent = cpuid->nent;
+ r = kvm_check_cpuid(vcpu);
+ if (r) {
+ vcpu->arch.cpuid_nent = 0;
+ goto out;
+ }
+
kvm_apic_set_version(vcpu);
kvm_x86_ops.cpuid_update(vcpu);
- r = kvm_update_cpuid(vcpu);
- if (r)
- vcpu->arch.cpuid_nent = 0;
+ kvm_update_cpuid(vcpu);
out:
return r;
}
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index 05434cd9342f..f136de1debad 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -9,7 +9,7 @@
extern u32 kvm_cpu_caps[NCAPINTS] __read_mostly;
void kvm_set_cpu_caps(void);
-int kvm_update_cpuid(struct kvm_vcpu *vcpu);
+void kvm_update_cpuid(struct kvm_vcpu *vcpu);
struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
u32 function, u32 index);
int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid,
--
2.18.4
next prev parent reply other threads:[~2020-07-08 6:51 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-08 6:50 [PATCH v3 0/8] Refactor handling flow of KVM_SET_CPUID* Xiaoyao Li
2020-07-08 6:50 ` [PATCH v3 1/8] KVM: X86: Reset vcpu->arch.cpuid_nent to 0 if SET_CPUID* fails Xiaoyao Li
2020-07-08 12:00 ` Paolo Bonzini
2020-07-08 6:50 ` [PATCH v3 2/8] KVM: X86: Go on updating other CPUID leaves when leaf 1 is absent Xiaoyao Li
2020-07-08 6:50 ` Xiaoyao Li [this message]
2020-07-08 12:28 ` [PATCH v3 3/8] KVM: X86: Introduce kvm_check_cpuid() Xiaoyao Li
2020-07-08 12:43 ` Paolo Bonzini
2020-07-08 6:50 ` [PATCH v3 4/8] KVM: X86: Split kvm_update_cpuid() Xiaoyao Li
2020-07-08 12:06 ` Paolo Bonzini
2020-07-08 12:33 ` Xiaoyao Li
2020-07-08 12:41 ` Paolo Bonzini
2020-07-08 13:27 ` Xiaoyao Li
2020-07-08 13:30 ` Paolo Bonzini
2020-07-08 6:50 ` [PATCH v3 5/8] KVM: X86: Rename cpuid_update() to update_vcpu_model() Xiaoyao Li
2020-07-08 12:08 ` Paolo Bonzini
2020-07-08 6:50 ` [PATCH v3 6/8] KVM: X86: Move kvm_x86_ops.update_vcpu_model() into kvm_update_vcpu_model() Xiaoyao Li
2020-07-08 6:50 ` [PATCH v3 7/8] KVM: lapic: Use guest_cpuid_has() in kvm_apic_set_version() Xiaoyao Li
2020-07-08 6:50 ` [PATCH v3 8/8] KVM: X86: Move kvm_apic_set_version() to kvm_update_vcpu_model() Xiaoyao Li
2020-07-08 12:10 ` [PATCH v3 0/8] Refactor handling flow of KVM_SET_CPUID* Paolo Bonzini
2020-07-09 4:27 ` Xiaoyao Li
2020-07-09 9:37 ` Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200708065054.19713-4-xiaoyao.li@intel.com \
--to=xiaoyao.li@intel.com \
--cc=corbet@lwn.net \
--cc=jmattson@google.com \
--cc=joro@8bytes.org \
--cc=kvm@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=sean.j.christopherson@intel.com \
--cc=vkuznets@redhat.com \
--cc=wanpengli@tencent.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox