If the guest requests string I/O from the hypervisor via VMGEXIT, SW_EXITINFO2 will contain the REP count. However, sev_es_string_io was incorrectly treating it as the size of the GHCB buffer in bytes.
This fixes the "outsw" test in the experimental SEV tests of kvm-unit-tests.
Cc: stable@vger.kernel.org Fixes: 7ed9abfe8e9f ("KVM: SVM: Support string IO operations for an SEV-ES guest") Reported-by: Marc Orr marcorr@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com --- arch/x86/kvm/svm/sev.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index e672493b5d8d..12d29d669cbc 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -2579,11 +2579,16 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in) { - if (!setup_vmgexit_scratch(svm, in, svm->vmcb->control.exit_info_2)) + u32 bytes; + + if (unlikely(check_mul_overflow(svm->vmcb->control.exit_info_2, size, &bytes))) + return -EINVAL; + + if (!setup_vmgexit_scratch(svm, in, bytes)) return -EINVAL;
- return kvm_sev_es_string_io(&svm->vcpu, size, port, - svm->ghcb_sa, svm->ghcb_sa_len / size, in); + return kvm_sev_es_string_io(&svm->vcpu, size, port, svm->ghcb_sa, + svm->vmcb->control.exit_info_2, in); }
void sev_es_init_vmcb(struct vcpu_svm *svm)
On Mon, Oct 25, 2021 at 9:25 AM Paolo Bonzini pbonzini@redhat.com wrote:
If the guest requests string I/O from the hypervisor via VMGEXIT, SW_EXITINFO2 will contain the REP count. However, sev_es_string_io was incorrectly treating it as the size of the GHCB buffer in bytes.
This fixes the "outsw" test in the experimental SEV tests of kvm-unit-tests.
Cc: stable@vger.kernel.org Fixes: 7ed9abfe8e9f ("KVM: SVM: Support string IO operations for an SEV-ES guest") Reported-by: Marc Orr marcorr@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com
arch/x86/kvm/svm/sev.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index e672493b5d8d..12d29d669cbc 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -2579,11 +2579,16 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in) {
if (!setup_vmgexit_scratch(svm, in, svm->vmcb->control.exit_info_2))
u32 bytes;
if (unlikely(check_mul_overflow(svm->vmcb->control.exit_info_2, size, &bytes)))
return -EINVAL;
Maybe this is only an issue on our internal setup, but when I tested this I found that `check_mul_overflow()` is very particular that all three args having the same type. Therefore, to get it to compile, I changed all of the arguments to match the type of `exit_info_2`, like so:
u64 bytes;
if (unlikely(check_mul_overflow(svm->vmcb->control.exit_info_2, (u64)size, &bytes)))
if (!setup_vmgexit_scratch(svm, in, bytes)) return -EINVAL;
return kvm_sev_es_string_io(&svm->vcpu, size, port,
svm->ghcb_sa, svm->ghcb_sa_len / size, in);
return kvm_sev_es_string_io(&svm->vcpu, size, port, svm->ghcb_sa,
svm->vmcb->control.exit_info_2, in);
}
void sev_es_init_vmcb(struct vcpu_svm *svm)
2.27.0
I've tested that this works. To test it, I (temporarily) modified `setup_vmgexit_scratch()` to always treat the scratch area as if it resides outside of the GHCB page (i.e., always go down the `else` code path). Doing this, I was able to see the stringio test case fail before this patch and pass with it.
Reviewed-by: Marc Orr marcorr@google.com Tested-by: Marc Orr marcorr@google.com
linux-stable-mirror@lists.linaro.org