Skip to content

Commit 15f9017

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/vgic-ipa-checks into kvmarm-master/next
* kvm-arm64/vgic-ipa-checks: : . : Add extra checks to prevent ther various GIC regions to land : outside of the IPA space (and tests to verify that it works). : . KVM: arm64: selftests: Add init ITS device test KVM: arm64: selftests: Add test for legacy GICv3 REDIST base partially above IPA range KVM: arm64: selftests: Add tests for GIC redist/cpuif partially above IPA range KVM: arm64: selftests: Add some tests for GICv2 in vgic_init KVM: arm64: selftests: Make vgic_init/vm_gic_create version agnostic KVM: arm64: selftests: Make vgic_init gic version agnostic KVM: arm64: vgic: Drop vgic_check_ioaddr() KVM: arm64: vgic-v3: Check ITS region is not above the VM IPA size KVM: arm64: vgic-v2: Check cpu interface region is not above the VM IPA size KVM: arm64: vgic-v3: Check redist region is not above the VM IPA size kvm: arm64: vgic: Introduce vgic_check_iorange Signed-off-by: Marc Zyngier <[email protected]>
2 parents 3864d17 + 3e197f1 commit 15f9017

File tree

6 files changed

+298
-114
lines changed

6 files changed

+298
-114
lines changed

arch/arm64/kvm/vgic/vgic-its.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2710,8 +2710,8 @@ static int vgic_its_set_attr(struct kvm_device *dev,
27102710
if (copy_from_user(&addr, uaddr, sizeof(addr)))
27112711
return -EFAULT;
27122712

2713-
ret = vgic_check_ioaddr(dev->kvm, &its->vgic_its_base,
2714-
addr, SZ_64K);
2713+
ret = vgic_check_iorange(dev->kvm, its->vgic_its_base,
2714+
addr, SZ_64K, KVM_VGIC_V3_ITS_SIZE);
27152715
if (ret)
27162716
return ret;
27172717

arch/arm64/kvm/vgic/vgic-kvm-device.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,21 @@
1414

1515
/* common helpers */
1616

17-
int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
18-
phys_addr_t addr, phys_addr_t alignment)
17+
int vgic_check_iorange(struct kvm *kvm, phys_addr_t ioaddr,
18+
phys_addr_t addr, phys_addr_t alignment,
19+
phys_addr_t size)
1920
{
20-
if (addr & ~kvm_phys_mask(kvm))
21-
return -E2BIG;
21+
if (!IS_VGIC_ADDR_UNDEF(ioaddr))
22+
return -EEXIST;
2223

23-
if (!IS_ALIGNED(addr, alignment))
24+
if (!IS_ALIGNED(addr, alignment) || !IS_ALIGNED(size, alignment))
2425
return -EINVAL;
2526

26-
if (!IS_VGIC_ADDR_UNDEF(*ioaddr))
27-
return -EEXIST;
27+
if (addr + size < addr)
28+
return -EINVAL;
29+
30+
if (addr & ~kvm_phys_mask(kvm) || addr + size > kvm_phys_size(kvm))
31+
return -E2BIG;
2832

2933
return 0;
3034
}
@@ -57,7 +61,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
5761
{
5862
int r = 0;
5963
struct vgic_dist *vgic = &kvm->arch.vgic;
60-
phys_addr_t *addr_ptr, alignment;
64+
phys_addr_t *addr_ptr, alignment, size;
6165
u64 undef_value = VGIC_ADDR_UNDEF;
6266

6367
mutex_lock(&kvm->lock);
@@ -66,16 +70,19 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
6670
r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
6771
addr_ptr = &vgic->vgic_dist_base;
6872
alignment = SZ_4K;
73+
size = KVM_VGIC_V2_DIST_SIZE;
6974
break;
7075
case KVM_VGIC_V2_ADDR_TYPE_CPU:
7176
r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
7277
addr_ptr = &vgic->vgic_cpu_base;
7378
alignment = SZ_4K;
79+
size = KVM_VGIC_V2_CPU_SIZE;
7480
break;
7581
case KVM_VGIC_V3_ADDR_TYPE_DIST:
7682
r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V3);
7783
addr_ptr = &vgic->vgic_dist_base;
7884
alignment = SZ_64K;
85+
size = KVM_VGIC_V3_DIST_SIZE;
7986
break;
8087
case KVM_VGIC_V3_ADDR_TYPE_REDIST: {
8188
struct vgic_redist_region *rdreg;
@@ -140,7 +147,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
140147
goto out;
141148

142149
if (write) {
143-
r = vgic_check_ioaddr(kvm, addr_ptr, *addr, alignment);
150+
r = vgic_check_iorange(kvm, *addr_ptr, *addr, alignment, size);
144151
if (!r)
145152
*addr_ptr = *addr;
146153
} else {

arch/arm64/kvm/vgic/vgic-mmio-v3.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,9 @@ static int vgic_v3_alloc_redist_region(struct kvm *kvm, uint32_t index,
796796
struct vgic_dist *d = &kvm->arch.vgic;
797797
struct vgic_redist_region *rdreg;
798798
struct list_head *rd_regions = &d->rd_regions;
799-
size_t size = count * KVM_VGIC_V3_REDIST_SIZE;
799+
int nr_vcpus = atomic_read(&kvm->online_vcpus);
800+
size_t size = count ? count * KVM_VGIC_V3_REDIST_SIZE
801+
: nr_vcpus * KVM_VGIC_V3_REDIST_SIZE;
800802
int ret;
801803

802804
/* cross the end of memory ? */
@@ -840,7 +842,7 @@ static int vgic_v3_alloc_redist_region(struct kvm *kvm, uint32_t index,
840842

841843
rdreg->base = VGIC_ADDR_UNDEF;
842844

843-
ret = vgic_check_ioaddr(kvm, &rdreg->base, base, SZ_64K);
845+
ret = vgic_check_iorange(kvm, rdreg->base, base, SZ_64K, size);
844846
if (ret)
845847
goto free;
846848

arch/arm64/kvm/vgic/vgic-v3.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -483,8 +483,10 @@ bool vgic_v3_check_base(struct kvm *kvm)
483483
return false;
484484

485485
list_for_each_entry(rdreg, &d->rd_regions, list) {
486-
if (rdreg->base + vgic_v3_rd_region_size(kvm, rdreg) <
487-
rdreg->base)
486+
size_t sz = vgic_v3_rd_region_size(kvm, rdreg);
487+
488+
if (vgic_check_iorange(kvm, VGIC_ADDR_UNDEF,
489+
rdreg->base, SZ_64K, sz))
488490
return false;
489491
}
490492

arch/arm64/kvm/vgic/vgic.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,9 @@ void vgic_kick_vcpus(struct kvm *kvm);
172172
void vgic_irq_handle_resampling(struct vgic_irq *irq,
173173
bool lr_deactivated, bool lr_pending);
174174

175-
int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
176-
phys_addr_t addr, phys_addr_t alignment);
175+
int vgic_check_iorange(struct kvm *kvm, phys_addr_t ioaddr,
176+
phys_addr_t addr, phys_addr_t alignment,
177+
phys_addr_t size);
177178

178179
void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
179180
void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);

0 commit comments

Comments
 (0)