Skip to content

Commit cafe7e5

Browse files
Ricardo KollerMarc Zyngier
authored andcommitted
KVM: arm64: vgic: Check that new ITEs could be saved in guest memory
Try to improve the predictability of ITS save/restores by failing commands that would lead to failed saves. More specifically, fail any command that adds an entry into an ITS table that is not in guest memory, which would otherwise lead to a failed ITS save ioctl. There are already checks for collection and device entries, but not for ITEs. Add the corresponding check for the ITT when adding ITEs. Reviewed-by: Eric Auger <eric.auger@redhat.com> Signed-off-by: Ricardo Koller <ricarkol@google.com> Reviewed-by: Oliver Upton <oupton@google.com> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20220510001633.552496-2-ricarkol@google.com
1 parent b2d229d commit cafe7e5

1 file changed

Lines changed: 35 additions & 12 deletions

File tree

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

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,18 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
894894
return update_affinity(ite->irq, vcpu);
895895
}
896896

897+
static bool __is_visible_gfn_locked(struct vgic_its *its, gpa_t gpa)
898+
{
899+
gfn_t gfn = gpa >> PAGE_SHIFT;
900+
int idx;
901+
bool ret;
902+
903+
idx = srcu_read_lock(&its->dev->kvm->srcu);
904+
ret = kvm_is_visible_gfn(its->dev->kvm, gfn);
905+
srcu_read_unlock(&its->dev->kvm->srcu, idx);
906+
return ret;
907+
}
908+
897909
/*
898910
* Check whether an ID can be stored into the corresponding guest table.
899911
* For a direct table this is pretty easy, but gets a bit nasty for
@@ -908,9 +920,7 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id,
908920
u64 indirect_ptr, type = GITS_BASER_TYPE(baser);
909921
phys_addr_t base = GITS_BASER_ADDR_48_to_52(baser);
910922
int esz = GITS_BASER_ENTRY_SIZE(baser);
911-
int index, idx;
912-
gfn_t gfn;
913-
bool ret;
923+
int index;
914924

915925
switch (type) {
916926
case GITS_BASER_TYPE_DEVICE:
@@ -933,12 +943,11 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id,
933943
return false;
934944

935945
addr = base + id * esz;
936-
gfn = addr >> PAGE_SHIFT;
937946

938947
if (eaddr)
939948
*eaddr = addr;
940949

941-
goto out;
950+
return __is_visible_gfn_locked(its, addr);
942951
}
943952

944953
/* calculate and check the index into the 1st level */
@@ -964,16 +973,30 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id,
964973
/* Find the address of the actual entry */
965974
index = id % (SZ_64K / esz);
966975
indirect_ptr += index * esz;
967-
gfn = indirect_ptr >> PAGE_SHIFT;
968976

969977
if (eaddr)
970978
*eaddr = indirect_ptr;
971979

972-
out:
973-
idx = srcu_read_lock(&its->dev->kvm->srcu);
974-
ret = kvm_is_visible_gfn(its->dev->kvm, gfn);
975-
srcu_read_unlock(&its->dev->kvm->srcu, idx);
976-
return ret;
980+
return __is_visible_gfn_locked(its, indirect_ptr);
981+
}
982+
983+
/*
984+
* Check whether an event ID can be stored in the corresponding Interrupt
985+
* Translation Table, which starts at device->itt_addr.
986+
*/
987+
static bool vgic_its_check_event_id(struct vgic_its *its, struct its_device *device,
988+
u32 event_id)
989+
{
990+
const struct vgic_its_abi *abi = vgic_its_get_abi(its);
991+
int ite_esz = abi->ite_esz;
992+
gpa_t gpa;
993+
994+
/* max table size is: BIT_ULL(device->num_eventid_bits) * ite_esz */
995+
if (event_id >= BIT_ULL(device->num_eventid_bits))
996+
return false;
997+
998+
gpa = device->itt_addr + event_id * ite_esz;
999+
return __is_visible_gfn_locked(its, gpa);
9771000
}
9781001

9791002
static int vgic_its_alloc_collection(struct vgic_its *its,
@@ -1061,7 +1084,7 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
10611084
if (!device)
10621085
return E_ITS_MAPTI_UNMAPPED_DEVICE;
10631086

1064-
if (event_id >= BIT_ULL(device->num_eventid_bits))
1087+
if (!vgic_its_check_event_id(its, device, event_id))
10651088
return E_ITS_MAPTI_ID_OOR;
10661089

10671090
if (its_cmd_get_command(its_cmd) == GITS_CMD_MAPTI)

0 commit comments

Comments
 (0)