* [PATCH 1/3] KVM: arm64: Clear the whole hugetlb folio when sanitising MTE tags
2026-10-19 13:21 [PATCH 0/3] KVM: arm64: Fix stale MTE tags reaching a guest Fuad Tabba
@ 2026-10-19 13:21 ` Fuad Tabba
2026-10-19 13:21 ` [PATCH 2/3] KVM: arm64: Clear the whole hugetlb folio when storing " Fuad Tabba
2026-10-19 13:21 ` [PATCH 3/3] KVM: arm64: Sanitise MTE tags when a permission fault installs a mapping Fuad Tabba
2 siblings, 0 replies; 4+ messages in thread
From: Fuad Tabba @ 2026-10-19 13:21 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, kvmarm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Zenghui Yu, Steffen Eiden,
Catalin Marinas, Will Deacon, Mark Rutland, Steven Price,
Yang Shi, David Hildenbrand, Fuad Tabba, linux-kernel
sanitise_mte_tags() clears the tags of the pages about to be mapped at
stage-2 before marking them tagged. For a hugetlb folio the flag covers
every page in the folio, but the loop only covers the mapping being
installed. Stage-2 maps a folio in pieces for the contiguous hugetlb
sizes, and for any size under dirty logging. The first fault then marks
the whole folio after clearing only its own piece, and the rest keeps
its previous owner's tags for the guest to read.
Clear the whole folio, as mte_sync_tags() does.
Fixes: 25c17c4b55def ("hugetlb: arm64: add mte support")
Cc: stable@vger.kernel.org
Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
---
arch/arm64/kvm/mmu.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 9ba86450fe4af..48a08b608ea72 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1514,7 +1514,8 @@ static void sanitise_mte_tags(struct kvm *kvm, kvm_pfn_t pfn,
if (folio_test_hugetlb(folio)) {
/* Hugetlb has MTE flags set on head page only */
if (folio_try_hugetlb_mte_tagging(folio)) {
- for (i = 0; i < nr_pages; i++, page++)
+ page = folio_page(folio, 0);
+ for (i = 0; i < folio_nr_pages(folio); i++, page++)
mte_clear_page_tags(page_address(page));
folio_set_hugetlb_mte_tagged(folio);
}
--
2.47.3
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 2/3] KVM: arm64: Clear the whole hugetlb folio when storing MTE tags
2026-10-19 13:21 [PATCH 0/3] KVM: arm64: Fix stale MTE tags reaching a guest Fuad Tabba
2026-10-19 13:21 ` [PATCH 1/3] KVM: arm64: Clear the whole hugetlb folio when sanitising MTE tags Fuad Tabba
@ 2026-10-19 13:21 ` Fuad Tabba
2026-10-19 13:21 ` [PATCH 3/3] KVM: arm64: Sanitise MTE tags when a permission fault installs a mapping Fuad Tabba
2 siblings, 0 replies; 4+ messages in thread
From: Fuad Tabba @ 2026-10-19 13:21 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, kvmarm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Zenghui Yu, Steffen Eiden,
Catalin Marinas, Will Deacon, Mark Rutland, Steven Price,
Yang Shi, David Hildenbrand, Fuad Tabba, linux-kernel
When KVM_ARM_MTE_COPY_TAGS copies tags into a page, it marks the page as
tagged. For a hugetlb folio the flag covers every page in the folio. If
the folio wasn't tagged yet, its other pages are marked as tagged with
their previous owner's tags still in place. The stage-2 fault path then
maps them into the guest without clearing them. The ioctl's read side
also copies them out to the VMM.
Clear the whole folio on its first tagging, before copying in this
page's tags.
Fixes: 25c17c4b55def ("hugetlb: arm64: add mte support")
Cc: stable@vger.kernel.org
Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
---
arch/arm64/kvm/guest.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index b01d6622b8720..cda655fbff657 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -1012,6 +1012,7 @@ int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
void *maddr;
unsigned long num_tags;
struct folio *folio;
+ unsigned long i;
if (!page) {
ret = -EFAULT;
@@ -1042,12 +1043,14 @@ int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
/*
* Only locking to serialise with a concurrent
* __set_ptes() in the VMM but still overriding the
- * tags, hence ignoring the return value.
+ * tags. A hugetlb folio is marked tagged as a whole,
+ * so its first tagging clears every page.
*/
- if (folio_test_hugetlb(folio))
- folio_try_hugetlb_mte_tagging(folio);
- else
+ if (!folio_test_hugetlb(folio))
try_page_mte_tagging(page);
+ else if (folio_try_hugetlb_mte_tagging(folio))
+ for (i = 0; i < folio_nr_pages(folio); i++)
+ mte_clear_page_tags(page_address(folio_page(folio, i)));
num_tags = mte_copy_tags_from_user(maddr, tags,
MTE_GRANULES_PER_PAGE);
--
2.47.3
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 3/3] KVM: arm64: Sanitise MTE tags when a permission fault installs a mapping
2026-10-19 13:21 [PATCH 0/3] KVM: arm64: Fix stale MTE tags reaching a guest Fuad Tabba
2026-10-19 13:21 ` [PATCH 1/3] KVM: arm64: Clear the whole hugetlb folio when sanitising MTE tags Fuad Tabba
2026-10-19 13:21 ` [PATCH 2/3] KVM: arm64: Clear the whole hugetlb folio when storing " Fuad Tabba
@ 2026-10-19 13:21 ` Fuad Tabba
2 siblings, 0 replies; 4+ messages in thread
From: Fuad Tabba @ 2026-10-19 13:21 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, kvmarm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Zenghui Yu, Steffen Eiden,
Catalin Marinas, Will Deacon, Mark Rutland, Steven Price,
Yang Shi, David Hildenbrand, Fuad Tabba, linux-kernel
The stage-2 fault path sanitises MTE tags only on translation faults, as
a permission fault normally just relaxes an existing leaf. However, when
the page is backed by a THP, a permission fault at page granule installs
a block whose other pages may never have been mapped or sanitised. Once
dirty logging is off, a guest write to a page mapped read-only during
logging installs the block, and the guest can read the tags those pages'
previous owners left.
Sanitise whenever the fault path calls kvm_pgtable_stage2_map() rather
than relaxing permissions. If the VMM replaces the VMA after the guest
takes a permission fault but before vma_lookup(), that path would map
and sanitise memory from the new VMA without checking it. Run the
VM_MTE_ALLOWED check in kvm_s2_fault_compute_prot() on permission
faults too.
Fixes: ea7fc1bb1cd1b ("KVM: arm64: Introduce MTE VM feature")
Cc: stable@vger.kernel.org
Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev>
---
arch/arm64/kvm/mmu.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 48a08b608ea72..208fcae80f67f 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -2005,7 +2005,7 @@ static int kvm_s2_fault_compute_prot(const struct kvm_s2_fault_desc *s2fd,
if (s2fd->nested)
*prot = adjust_nested_exec_perms(kvm, s2fd->nested, *prot);
- if (!kvm_s2_fault_is_perm(s2fd) && !s2vi->map_non_cacheable && kvm_has_mte(kvm)) {
+ if (!s2vi->map_non_cacheable && kvm_has_mte(kvm)) {
/* Check the VMM hasn't introduced a new disallowed VMA */
if (!s2vi->mte_allowed)
return -EFAULT;
@@ -2060,7 +2060,7 @@ static int kvm_s2_fault_map(const struct kvm_s2_fault_desc *s2fd,
}
}
- if (!perm_fault_granule && !s2vi->map_non_cacheable && kvm_has_mte(kvm))
+ if (mapping_size != perm_fault_granule && !s2vi->map_non_cacheable && kvm_has_mte(kvm))
sanitise_mte_tags(kvm, pfn, mapping_size);
/*
--
2.47.3
^ permalink raw reply [flat|nested] 4+ messages in thread