From: Sean Christopherson <seanjc@google.com>
To: Vitaly Kuznetsov <vkuznets@redhat.com>
Cc: kvm@vger.kernel.org, Paolo Bonzini <pbonzini@redhat.com>,
Wanpeng Li <wanpengli@tencent.com>,
Jim Mattson <jmattson@google.com>,
Igor Mammedov <imammedo@redhat.com>,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3 2/4] KVM: x86: Partially allow KVM_SET_CPUID{,2} after KVM_RUN
Date: Tue, 18 Jan 2022 16:37:47 +0000 [thread overview]
Message-ID: <Yebs21Vnt4WBQBw5@google.com> (raw)
In-Reply-To: <20220118141801.2219924-3-vkuznets@redhat.com>
On Tue, Jan 18, 2022, Vitaly Kuznetsov wrote:
> +/* Check whether the supplied CPUID data is equal to what is already set for the vCPU. */
> +static int kvm_cpuid_check_equal(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *e2,
> + int nent)
> +{
> + struct kvm_cpuid_entry2 *orig;
> + int i;
> +
> + if (nent != vcpu->arch.cpuid_nent)
> + return -EINVAL;
> +
> + for (i = 0; i < nent; i++) {
> + orig = &vcpu->arch.cpuid_entries[i];
> + if (e2[i].function != orig->function ||
> + e2[i].index != orig->index ||
> + e2[i].eax != orig->eax || e2[i].ebx != orig->ebx ||
> + e2[i].ecx != orig->ecx || e2[i].edx != orig->edx)
> + return -EINVAL;
This needs to check .flags for the above check on .index to be meaningful, and at
that point, can't we be even more agressive and just do?
if (memcmp(e2, vcpu->arch.cpuid_entries, nent * sizeof(e2)))
return -EINVAL;
return 0;
> + }
> +
> + return 0;
> +}
> +
> static void kvm_update_kvm_cpuid_base(struct kvm_vcpu *vcpu)
> {
> u32 function;
> @@ -313,6 +335,20 @@ static int kvm_set_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *e2,
>
> __kvm_update_cpuid_runtime(vcpu, e2, nent);
> + /*
> + * KVM does not correctly handle changing guest CPUID after KVM_RUN, as
> + * MAXPHYADDR, GBPAGES support, AMD reserved bit behavior, etc.. aren't
> + * tracked in kvm_mmu_page_role. As a result, KVM may miss guest page
> + * faults due to reusing SPs/SPTEs. In practice no sane VMM mucks with
> + * the core vCPU model on the fly. It would've been better to forbid any
> + * KVM_SET_CPUID{,2} calls after KVM_RUN altogether but unfortunately
> + * some VMMs (e.g. QEMU) reuse vCPU fds for CPU hotplug/unplug and do
> + * KVM_SET_CPUID{,2} again. To support this legacy behavior, check
> + * whether the supplied CPUID data is equal to what's already set.
This is misleading/wrong. KVM_RUN isn't the only problematic ioctl(), it's just
the one that we decided to use to detect that userspace is being stupid. And
forbidding KVM_SET_CPUID after KVM_RUN (or even all problematic ioctls()) wouldn't
solve problem as providing different CPUID configurations for vCPUs in a VM will
also cause the MMU to fall on its face.
> + if (vcpu->arch.last_vmentry_cpu != -1)
> + return kvm_cpuid_check_equal(vcpu, e2, nent);
And technically, checking last_vmentry_cpu doesn't forbid changing CPUID after
KVM_RUN, it forbids changing CPUID after successfully entering the guest (or
emulating instructions on VMX).
I realize I'm being very pedantic, as a well-intended userspace is obviously not
going to change CPUID after -EINTR or whatever. But I do want to highlight that
this approach is by no means bulletproof, and that what is/isn't allowed with
respect to guest CPUID isn't necessarily associated with what is/isn't "safe".
In other words, this check doesn't guarantee that userspace can't misuse KVM_SET_CPUID,
and on the flip side it disallows using KVM_SET_CPUID in ways that are perfectly ok
(if userspace is careful and deliberate).
next prev parent reply other threads:[~2022-01-18 16:37 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-01-18 14:17 [PATCH v3 0/4] KVM: x86: Partially allow KVM_SET_CPUID{,2} after KVM_RUN for CPU hotplug Vitaly Kuznetsov
2022-01-18 14:17 ` [PATCH v3 1/4] KVM: x86: Do runtime CPUID update before updating vcpu->arch.cpuid_entries Vitaly Kuznetsov
2022-01-18 14:17 ` [PATCH v3 2/4] KVM: x86: Partially allow KVM_SET_CPUID{,2} after KVM_RUN Vitaly Kuznetsov
2022-01-18 16:37 ` Sean Christopherson [this message]
2022-01-19 10:02 ` Vitaly Kuznetsov
2022-01-19 17:40 ` Sean Christopherson
2022-01-18 14:18 ` [PATCH v3 3/4] KVM: selftests: Rename 'get_cpuid_test' to 'cpuid_test' Vitaly Kuznetsov
2022-01-18 14:18 ` [PATCH v3 4/4] KVM: selftests: Test KVM_SET_CPUID2 after KVM_RUN Vitaly Kuznetsov
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=Yebs21Vnt4WBQBw5@google.com \
--to=seanjc@google.com \
--cc=imammedo@redhat.com \
--cc=jmattson@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.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 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.