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: 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-4-ricarkol@google.com
This commit is contained in:
parent
4612d98f58
commit
c56a87da0a
@ -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)
|
|||||||
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)
|
|||||||
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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user