From: David Woodhouse <[email protected]>

HvCallSendSyntheticClusterIpi(Ex) honours the target VTL in its input
but does not check it against the caller's VTL. A guest running in a
lower VTL can therefore assert any fixed interrupt in a higher VTL on
any VP, which crosses the boundary that VTLs exist to enforce.

Refuse a target VTL above the caller's with HV_STATUS_ACCESS_DENIED.
A VTL may still interrupt its own level and lower ones.  The old
upper-bound check on the target plane goes away: a target at or below
the caller's level is below KVM_MAX_PLANES by construction.

Matches the equivalent fix in the reference VSM implementation.  The
production Nitro Hypervisor permits the injection; the conformance
suite probes for either behaviour.

Signed-off-by: David Woodhouse <[email protected]>
Assisted-by: LLM
---
 arch/x86/kvm/hyperv.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 0bc9435ea3b9..e3ac840c8e5e 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -2710,13 +2710,21 @@ static int kvm_hv_send_ipi(struct kvm_vcpu *vcpu, 
struct kvm_hv_hcall *hc)
        if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
                return HV_STATUS_INVALID_HYPERCALL_INPUT;
 
-       /* TLFS: in_vtl bit 4 selects an explicit target VTL. */
-       if (in_vtl & 0x10)
+       /*
+        * TLFS: in_vtl bit 4 selects an explicit target VTL.  A VTL may
+        * interrupt its own level and lower ones, never a higher one
+        * (TLFS 15.9, "VTL Interrupt Management": each VTL sends and
+        * receives interrupts without interference from a less secure
+        * VTL).  The reference host omits this check; the suite's
+        * SendIpi test probes for both behaviours.
+        */
+       if (in_vtl & 0x10) {
                target_plane = in_vtl & 0xf;
-       else
+               if (target_plane > vcpu->plane_level)
+                       return HV_STATUS_ACCESS_DENIED;
+       } else {
                target_plane = vcpu->plane_level;
-       if (target_plane >= KVM_MAX_PLANES)
-               return HV_STATUS_INVALID_HYPERCALL_INPUT;
+       }
 
        if (all_cpus)
                kvm_hv_send_ipi_to_many(kvm, vector, NULL, 0, target_plane);
-- 
2.50.1


Reply via email to