KVM: VMX: Don't use vcpu->run->internal.ndata as an array index
authorReiji Watanabe <reijiw@google.com>
Tue, 13 Apr 2021 15:47:40 +0000 (15:47 +0000)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 13 Apr 2021 22:23:41 +0000 (18:23 -0400)
__vmx_handle_exit() uses vcpu->run->internal.ndata as an index for
an array access.  Since vcpu->run is (can be) mapped to a user address
space with a writer permission, the 'ndata' could be updated by the
user process at anytime (the user process can set it to outside the
bounds of the array).
So, it is not safe that __vmx_handle_exit() uses the 'ndata' that way.

Fixes: 1aa561b1a4c0 ("kvm: x86: Add "last CPU" to some KVM_EXIT information")
Signed-off-by: Reiji Watanabe <reijiw@google.com>
Reviewed-by: Jim Mattson <jmattson@google.com>
Message-Id: <20210413154739.490299-1-reijiw@google.com>
Cc: stable@vger.kernel.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/vmx/vmx.c

index 32cf8287d4a77306bb38da05ee6250441879e6f7..29b40e092d13db4dfc8664f001b9ce422f90b3e3 100644 (file)
@@ -6027,19 +6027,19 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
             exit_reason.basic != EXIT_REASON_PML_FULL &&
             exit_reason.basic != EXIT_REASON_APIC_ACCESS &&
             exit_reason.basic != EXIT_REASON_TASK_SWITCH)) {
+               int ndata = 3;
+
                vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
                vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_DELIVERY_EV;
-               vcpu->run->internal.ndata = 3;
                vcpu->run->internal.data[0] = vectoring_info;
                vcpu->run->internal.data[1] = exit_reason.full;
                vcpu->run->internal.data[2] = vcpu->arch.exit_qualification;
                if (exit_reason.basic == EXIT_REASON_EPT_MISCONFIG) {
-                       vcpu->run->internal.ndata++;
-                       vcpu->run->internal.data[3] =
+                       vcpu->run->internal.data[ndata++] =
                                vmcs_read64(GUEST_PHYSICAL_ADDRESS);
                }
-               vcpu->run->internal.data[vcpu->run->internal.ndata++] =
-                       vcpu->arch.last_vmentry_cpu;
+               vcpu->run->internal.data[ndata++] = vcpu->arch.last_vmentry_cpu;
+               vcpu->run->internal.ndata = ndata;
                return 0;
        }