Commit 40421f38 authored by Sean Christopherson's avatar Sean Christopherson Committed by Paolo Bonzini

KVM: x86: Reject fixeds-size Hyper-V hypercalls with non-zero "var_cnt"

Reject Hyper-V hypercalls if the guest specifies a non-zero variable size
header (var_cnt in KVM) for a hypercall that has a fixed header size.
Per the TLFS:

  It is illegal to specify a non-zero variable header size for a
  hypercall that is not explicitly documented as accepting variable sized
  input headers. In such a case the hypercall will result in a return
  code of HV_STATUS_INVALID_HYPERCALL_INPUT.

Note, at least some of the various DEBUG commands likely aren't allowed
to use variable size headers, but the TLFS documentation doesn't clearly
state what is/isn't allowed.  Omit them for now to avoid unnecessary
breakage.
Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
Reviewed-by: default avatarVitaly Kuznetsov <vkuznets@redhat.com>
Message-Id: <20211207220926.718794-8-seanjc@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 9c52f6b3
...@@ -2253,14 +2253,14 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) ...@@ -2253,14 +2253,14 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
switch (hc.code) { switch (hc.code) {
case HVCALL_NOTIFY_LONG_SPIN_WAIT: case HVCALL_NOTIFY_LONG_SPIN_WAIT:
if (unlikely(hc.rep)) { if (unlikely(hc.rep || hc.var_cnt)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT; ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break; break;
} }
kvm_vcpu_on_spin(vcpu, true); kvm_vcpu_on_spin(vcpu, true);
break; break;
case HVCALL_SIGNAL_EVENT: case HVCALL_SIGNAL_EVENT:
if (unlikely(hc.rep)) { if (unlikely(hc.rep || hc.var_cnt)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT; ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break; break;
} }
...@@ -2270,7 +2270,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) ...@@ -2270,7 +2270,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
fallthrough; /* maybe userspace knows this conn_id */ fallthrough; /* maybe userspace knows this conn_id */
case HVCALL_POST_MESSAGE: case HVCALL_POST_MESSAGE:
/* don't bother userspace if it has no way to handle it */ /* don't bother userspace if it has no way to handle it */
if (unlikely(hc.rep || !to_hv_synic(vcpu)->active)) { if (unlikely(hc.rep || hc.var_cnt || !to_hv_synic(vcpu)->active)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT; ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break; break;
} }
...@@ -2283,14 +2283,14 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) ...@@ -2283,14 +2283,14 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
kvm_hv_hypercall_complete_userspace; kvm_hv_hypercall_complete_userspace;
return 0; return 0;
case HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST: case HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST:
if (unlikely(!hc.rep_cnt || hc.rep_idx)) { if (unlikely(!hc.rep_cnt || hc.rep_idx || hc.var_cnt)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT; ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break; break;
} }
ret = kvm_hv_flush_tlb(vcpu, &hc, false); ret = kvm_hv_flush_tlb(vcpu, &hc, false);
break; break;
case HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE: case HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE:
if (unlikely(hc.rep)) { if (unlikely(hc.rep || hc.var_cnt)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT; ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break; break;
} }
...@@ -2311,7 +2311,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) ...@@ -2311,7 +2311,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
ret = kvm_hv_flush_tlb(vcpu, &hc, true); ret = kvm_hv_flush_tlb(vcpu, &hc, true);
break; break;
case HVCALL_SEND_IPI: case HVCALL_SEND_IPI:
if (unlikely(hc.rep)) { if (unlikely(hc.rep || hc.var_cnt)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT; ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment