KVM_GET_CPUID2 never indicates the array length it populates. If an app passes in an array that's too short then kvm_vcpu_ioctl_get_cpuid2() populates the required array length and returns -E2BIG. However, its caller then just bails to "goto out", thus bypassing the copy_to_user(). If an app passes in an array that's not too short, then kvm_vcpu_ioctl_get_cpuid2() doesn't populate the array length. Its caller will then call copy_to_user(), which is pointless since no data values have been changed. This change attempts to have KVM_GET_CPUID2 populate the array length on both success and failure, and still indicate -E2BIG when a provided array is too short. I'm not sure if this type of change is considered an API breakage and thus we need a KVM_GET_CPUID3. Fixes: 0771671749b59 ("KVM: Enhance guest cpuid management", 2007-11-21) Signed-off-by: Matt Delco <delco@xxxxxxxxxxxx> --- arch/x86/kvm/cpuid.c | 1 + arch/x86/kvm/x86.c | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index f68c0c753c38..ec013b68b266 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -274,6 +274,7 @@ int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu, if (copy_to_user(entries, &vcpu->arch.cpuid_entries, vcpu->arch.cpuid_nent * sizeof(struct kvm_cpuid_entry2))) goto out; + cpuid->nent = vcpu->arch.cpuid_nent; return 0; out: diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 5863c38108d9..4998d3bafbfd 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4161,11 +4161,12 @@ long kvm_arch_vcpu_ioctl(struct file *filp, goto out; r = kvm_vcpu_ioctl_get_cpuid2(vcpu, &cpuid, cpuid_arg->entries); - if (r) + if (r && r != -E2BIG) goto out; - r = -EFAULT; - if (copy_to_user(cpuid_arg, &cpuid, sizeof(cpuid))) + if (copy_to_user(cpuid_arg, &cpuid, sizeof(cpuid))) { + r = -EFAULT; goto out; + } r = 0; break; } -- 2.23.0.866.gb869b98d4c-goog