Commit c56a87da authored by Ricardo Koller's avatar Ricardo Koller Committed by Marc Zyngier

KVM: arm64: vgic-v2: Check cpu interface region is not above the VM IPA size

Verify that the GICv2 CPU interface does not extend beyond the
VM-specified IPA range (phys_size).

  base + size > phys_size AND base < phys_size

Add the missing check into kvm_vgic_addr() which is called when setting
the region. This patch also enables some superfluous checks for the
distributor (vgic_check_ioaddr was enough as alignment == size for the
distributors).
Reviewed-by: default avatarEric Auger <eric.auger@redhat.com>
Signed-off-by: default avatarRicardo Koller <ricarkol@google.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20211005011921.437353-4-ricarkol@google.com
parent 4612d98f
...@@ -79,7 +79,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write) ...@@ -79,7 +79,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
{ {
int r = 0; int r = 0;
struct vgic_dist *vgic = &kvm->arch.vgic; struct vgic_dist *vgic = &kvm->arch.vgic;
phys_addr_t *addr_ptr, alignment; phys_addr_t *addr_ptr, alignment, size;
u64 undef_value = VGIC_ADDR_UNDEF; u64 undef_value = VGIC_ADDR_UNDEF;
mutex_lock(&kvm->lock); mutex_lock(&kvm->lock);
...@@ -88,16 +88,19 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write) ...@@ -88,16 +88,19 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2); r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
addr_ptr = &vgic->vgic_dist_base; addr_ptr = &vgic->vgic_dist_base;
alignment = SZ_4K; alignment = SZ_4K;
size = KVM_VGIC_V2_DIST_SIZE;
break; break;
case KVM_VGIC_V2_ADDR_TYPE_CPU: case KVM_VGIC_V2_ADDR_TYPE_CPU:
r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2); r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
addr_ptr = &vgic->vgic_cpu_base; addr_ptr = &vgic->vgic_cpu_base;
alignment = SZ_4K; alignment = SZ_4K;
size = KVM_VGIC_V2_CPU_SIZE;
break; break;
case KVM_VGIC_V3_ADDR_TYPE_DIST: case KVM_VGIC_V3_ADDR_TYPE_DIST:
r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V3); r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V3);
addr_ptr = &vgic->vgic_dist_base; addr_ptr = &vgic->vgic_dist_base;
alignment = SZ_64K; alignment = SZ_64K;
size = KVM_VGIC_V3_DIST_SIZE;
break; break;
case KVM_VGIC_V3_ADDR_TYPE_REDIST: { case KVM_VGIC_V3_ADDR_TYPE_REDIST: {
struct vgic_redist_region *rdreg; struct vgic_redist_region *rdreg;
...@@ -162,7 +165,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write) ...@@ -162,7 +165,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
goto out; goto out;
if (write) { if (write) {
r = vgic_check_ioaddr(kvm, addr_ptr, *addr, alignment); r = vgic_check_iorange(kvm, *addr_ptr, *addr, alignment, size);
if (!r) if (!r)
*addr_ptr = *addr; *addr_ptr = *addr;
} else { } else {
......
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