Verify that the redistributor regions do not extend beyond the
VM-specified IPA range (phys_size). This can happen when using
KVM_VGIC_V3_ADDR_TYPE_REDIST or KVM_VGIC_V3_ADDR_TYPE_REDIST_REGIONS
with:

  base + size > phys_size AND base < phys_size

Add the missing check into vgic_v3_alloc_redist_region() which is called
when setting the regions, and into vgic_v3_check_base() which is called
when attempting the first vcpu-run. The vcpu-run check does not apply to
KVM_VGIC_V3_ADDR_TYPE_REDIST_REGIONS because the regions size is known
before the first vcpu-run. Note that using the REDIST_REGIONS API
results in a different check, which already exists, at first vcpu run:
that the number of redist regions is enough for all vcpus.

Finally, this patch also enables some extra tests in
vgic_v3_alloc_redist_region() by calculating "size" early for the legacy
redist api: like checking that the REDIST region can fit all the already
created vcpus.

Signed-off-by: Ricardo Koller <[email protected]>
---
 arch/arm64/kvm/vgic/vgic-mmio-v3.c | 6 ++++--
 arch/arm64/kvm/vgic/vgic-v3.c      | 4 ++++
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c 
b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
index a09cdc0b953c..9be02bf7865e 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
@@ -796,7 +796,9 @@ static int vgic_v3_alloc_redist_region(struct kvm *kvm, 
uint32_t index,
        struct vgic_dist *d = &kvm->arch.vgic;
        struct vgic_redist_region *rdreg;
        struct list_head *rd_regions = &d->rd_regions;
-       size_t size = count * KVM_VGIC_V3_REDIST_SIZE;
+       int nr_vcpus = atomic_read(&kvm->online_vcpus);
+       size_t size = count ? count * KVM_VGIC_V3_REDIST_SIZE
+                           : nr_vcpus * KVM_VGIC_V3_REDIST_SIZE;
        int ret;
 
        /* cross the end of memory ? */
@@ -840,7 +842,7 @@ static int vgic_v3_alloc_redist_region(struct kvm *kvm, 
uint32_t index,
 
        rdreg->base = VGIC_ADDR_UNDEF;
 
-       ret = vgic_check_ioaddr(kvm, &rdreg->base, base, SZ_64K);
+       ret = vgic_check_iorange(kvm, &rdreg->base, base, SZ_64K, size);
        if (ret)
                goto free;
 
diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c
index 21a6207fb2ee..27ee674631b3 100644
--- a/arch/arm64/kvm/vgic/vgic-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-v3.c
@@ -486,6 +486,10 @@ bool vgic_v3_check_base(struct kvm *kvm)
                if (rdreg->base + vgic_v3_rd_region_size(kvm, rdreg) <
                        rdreg->base)
                        return false;
+
+               if (rdreg->base + vgic_v3_rd_region_size(kvm, rdreg) >
+                       kvm_phys_size(kvm))
+                       return false;
        }
 
        if (IS_VGIC_ADDR_UNDEF(d->vgic_dist_base))
-- 
2.33.0.685.g46640cef36-goog

_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

Reply via email to