]> www.infradead.org Git - users/willy/xarray.git/commitdiff
kvm: x86: Exclude unpermitted xfeatures at KVM_GET_SUPPORTED_CPUID
authorJing Liu <jing2.liu@intel.com>
Wed, 5 Jan 2022 12:35:15 +0000 (04:35 -0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 7 Jan 2022 18:33:04 +0000 (13:33 -0500)
KVM_GET_SUPPORTED_CPUID should not include any dynamic xstates in
CPUID[0xD] if they have not been requested with prctl. Otherwise
a process which directly passes KVM_GET_SUPPORTED_CPUID to
KVM_SET_CPUID2 would now fail even if it doesn't intend to use a
dynamically enabled feature. Userspace must know that prctl is
required and allocate >4K xstate buffer before setting any dynamic
bit.

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jing Liu <jing2.liu@intel.com>
Signed-off-by: Yang Zhong <yang.zhong@intel.com>
Message-Id: <20220105123532.12586-5-yang.zhong@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Documentation/virt/kvm/api.rst
arch/x86/kvm/cpuid.c

index 6b683dfea8f24a19f4a89151d7a855ecaa2a8a5a..f4ea5e41a4d0ca5b4b9681fa7352550a3f64d942 100644 (file)
@@ -1687,6 +1687,10 @@ userspace capabilities, and with user requirements (for example, the
 user may wish to constrain cpuid to emulate older hardware, or for
 feature consistency across a cluster).
 
+Dynamically-enabled feature bits need to be requested with
+``arch_prctl()`` before calling this ioctl. Feature bits that have not
+been requested are excluded from the result.
+
 Note that certain capabilities, such as KVM_CAP_X86_DISABLE_EXITS, may
 expose cpuid features (e.g. MONITOR) which are not supported by kvm in
 its default configuration. If userspace enables such capabilities, it
index f3e6fda6b858076c82b6b43ed64d113d516ea70d..eb52dde5deec1da1647b1224972d717ff8ff39e4 100644 (file)
@@ -815,11 +815,13 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
                                goto out;
                }
                break;
-       case 0xd:
-               entry->eax &= supported_xcr0;
+       case 0xd: {
+               u64 guest_perm = xstate_get_guest_group_perm();
+
+               entry->eax &= supported_xcr0 & guest_perm;
                entry->ebx = xstate_required_size(supported_xcr0, false);
                entry->ecx = entry->ebx;
-               entry->edx &= supported_xcr0 >> 32;
+               entry->edx &= (supported_xcr0 & guest_perm) >> 32;
                if (!supported_xcr0)
                        break;
 
@@ -866,6 +868,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
                        entry->edx = 0;
                }
                break;
+       }
        case 0x12:
                /* Intel SGX */
                if (!kvm_cpu_cap_has(X86_FEATURE_SGX)) {