diff mbox series

KVM: x86: return length in KVM_GET_CPUID2.

Message ID 20191024052918.140750-1-delco@chromium.org (mailing list archive)
State New, archived
Headers show
Series KVM: x86: return length in KVM_GET_CPUID2. | expand

Commit Message

Matt Delco Oct. 24, 2019, 5:29 a.m. UTC
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@chromium.org>
---
 arch/x86/kvm/cpuid.c | 1 +
 arch/x86/kvm/x86.c   | 7 ++++---
 2 files changed, 5 insertions(+), 3 deletions(-)
diff mbox series

Patch

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;
 	}