diff options
author | Ricardo Koller <ricarkol@google.com> | 2021-10-05 04:19:12 +0300 |
---|---|---|
committer | Marc Zyngier <maz@kernel.org> | 2021-10-11 11:31:41 +0300 |
commit | 4612d98f58c73ad63928200fd332f75c8e524dae (patch) | |
tree | b60a57f0637ed21e7fc9e73d9eb84b0ef2c59743 /arch/arm64/kvm/vgic/vgic-v3.c | |
parent | f25c5e4dafd859b941a4654cbab9eb83ff994bcd (diff) | |
download | linux-4612d98f58c73ad63928200fd332f75c8e524dae.tar.xz |
KVM: arm64: vgic-v3: Check redist region is not above the VM IPA size
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.
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Ricardo Koller <ricarkol@google.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20211005011921.437353-3-ricarkol@google.com
Diffstat (limited to 'arch/arm64/kvm/vgic/vgic-v3.c')
-rw-r--r-- | arch/arm64/kvm/vgic/vgic-v3.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c index 21a6207fb2ee..960f51a8691f 100644 --- a/arch/arm64/kvm/vgic/vgic-v3.c +++ b/arch/arm64/kvm/vgic/vgic-v3.c @@ -483,8 +483,10 @@ bool vgic_v3_check_base(struct kvm *kvm) return false; list_for_each_entry(rdreg, &d->rd_regions, list) { - if (rdreg->base + vgic_v3_rd_region_size(kvm, rdreg) < - rdreg->base) + size_t sz = vgic_v3_rd_region_size(kvm, rdreg); + + if (vgic_check_iorange(kvm, VGIC_ADDR_UNDEF, + rdreg->base, SZ_64K, sz)) return false; } |