summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuad Tabba <fuad.tabba@linux.dev>2026-08-07 11:41:01 +0100
committerOliver Upton <oupton@kernel.org>2026-08-07 09:06:27 -0700
commit9b10fb74e4b661543d188701bd4d024fc5c18f58 (patch)
treea662b420496304ef94347fbcf861e2b47d28b02b
parent52d044d6e76fcd48ee384f0628a39d56b04de95b (diff)
downloadlinux-stable-9b10fb74e4b661543d188701bd4d024fc5c18f58.tar.gz
linux-stable-9b10fb74e4b661543d188701bd4d024fc5c18f58.zip
KVM: arm64: vgic-its: Don't save collections the table cannot hold
A guest that disables the ITS and rewrites GITS_BASER with fewer pages, VALID still set, keeps every collection it mapped against the larger table: KVM stores the new BASER unconditionally and frees the list only when VALID is cleared. vgic_its_save_collection_table() then walks the whole list, writing up to 448K past the end of the table, and saves collection IDs that vgic_its_restore_cte() rejects, so the save succeeds and the restore fails with -EINVAL on the destination. The overrun stays in guest memory, as vgic_write_guest_lock() validates every gfn. Validate each collection against the current table with vgic_its_check_id() and return -EINVAL, as vgic_its_save_device_tables() does for devices. Collection IDs are unique and the collection table is never indirect, so the check also bounds the walk. Fixes: ea1ad53e1e31a ("KVM: arm64: vgic-its: Collection table save/restore") Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev> Link: https://patch.msgid.link/20260807104102.2410744-4-fuad.tabba@linux.dev Signed-off-by: Oliver Upton <oupton@kernel.org>
-rw-r--r--arch/arm64/kvm/vgic/vgic-its.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c
index 6f3ea75b4c23..d8b784f69abc 100644
--- a/arch/arm64/kvm/vgic/vgic-its.c
+++ b/arch/arm64/kvm/vgic/vgic-its.c
@@ -2529,6 +2529,9 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
max_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
list_for_each_entry(collection, &its->collection_list, coll_list) {
+ if (!vgic_its_check_id(its, baser, collection->collection_id, NULL))
+ return -EINVAL;
+
ret = vgic_its_save_cte(its, collection, gpa);
if (ret)
return ret;