]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: x86/xen: Restrict hypercall MSR to unofficial synthetic range
authorSean Christopherson <seanjc@google.com>
Sat, 15 Feb 2025 01:14:33 +0000 (17:14 -0800)
committerSean Christopherson <seanjc@google.com>
Mon, 24 Feb 2025 16:59:55 +0000 (08:59 -0800)
Reject userspace attempts to set the Xen hypercall page MSR to an index
outside of the "standard" virtualization range [0x40000000, 0x4fffffff],
as KVM is not equipped to handle collisions with real MSRs, e.g. KVM
doesn't update MSR interception, conflicts with VMCS/VMCB fields, special
case writes in KVM, etc.

While the MSR index isn't strictly ABI, i.e. can theoretically float to
any value, in practice no known VMM sets the MSR index to anything other
than 0x40000000 or 0x40000200.

Cc: Joao Martins <joao.m.martins@oracle.com>
Reviewed-by: David Woodhouse <dwmw@amazon.co.uk>
Reviewed-by: Paul Durrant <paul@xen.org>
Link: https://lore.kernel.org/r/20250215011437.1203084-2-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
Documentation/virt/kvm/api.rst
arch/x86/include/uapi/asm/kvm.h
arch/x86/kvm/xen.c

index 2b52eb77e29cba146b64489cfb1a267e7bb9b597..5fe84f2427b51efab37fe18111110b41fb034615 100644 (file)
@@ -1000,6 +1000,10 @@ blobs in userspace.  When the guest writes the MSR, kvm copies one
 page of a blob (32- or 64-bit, depending on the vcpu mode) to guest
 memory.
 
+The MSR index must be in the range [0x40000000, 0x4fffffff], i.e. must reside
+in the range that is unofficially reserved for use by hypervisors.  The min/max
+values are enumerated via KVM_XEN_MSR_MIN_INDEX and KVM_XEN_MSR_MAX_INDEX.
+
 ::
 
   struct kvm_xen_hvm_config {
index 9e75da97bce070a9054e678d951426d4ae072db6..460306b35a4bfee9e5e415b28e21f5382cca47f6 100644 (file)
@@ -559,6 +559,9 @@ struct kvm_x86_mce {
 #define KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE        (1 << 7)
 #define KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA     (1 << 8)
 
+#define KVM_XEN_MSR_MIN_INDEX                  0x40000000u
+#define KVM_XEN_MSR_MAX_INDEX                  0x4fffffffu
+
 struct kvm_xen_hvm_config {
        __u32 flags;
        __u32 msr;
index a909b817b9c0da1714169d937c135474e8a9cf7d..5b94825001a7a78660f0c386920aad89745615d7 100644 (file)
@@ -1324,6 +1324,15 @@ int kvm_xen_hvm_config(struct kvm *kvm, struct kvm_xen_hvm_config *xhc)
             xhc->blob_size_32 || xhc->blob_size_64))
                return -EINVAL;
 
+       /*
+        * Restrict the MSR to the range that is unofficially reserved for
+        * synthetic, virtualization-defined MSRs, e.g. to prevent confusing
+        * KVM by colliding with a real MSR that requires special handling.
+        */
+       if (xhc->msr &&
+           (xhc->msr < KVM_XEN_MSR_MIN_INDEX || xhc->msr > KVM_XEN_MSR_MAX_INDEX))
+               return -EINVAL;
+
        mutex_lock(&kvm->arch.xen.xen_lock);
 
        if (xhc->msr && !kvm->arch.xen_hvm_config.msr)