* [PATCH 0/3] KVM: arm64: Fix stale MTE tags reaching a guest
@ 2026-10-19 13:21 Fuad Tabba
2026-10-19 13:21 ` [PATCH 1/3] KVM: arm64: Clear the whole hugetlb folio when sanitising MTE tags Fuad Tabba
` (2 more replies)
0 siblings, 3 replies; 14+ 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
Hi folks,
Three fixes for hugetlb and THP pages that reach an MTE guest without
their tags cleared, so the guest can read whatever tags the pages'
previous owners left.
The first clears the whole of a hugetlb folio before marking it tagged,
rather than only the pages being mapped. The second does the same when
KVM_ARM_MTE_COPY_TAGS copies tags into a page. The third sanitises when
a permission fault installs a THP block, and runs the VM_MTE_ALLOWED
check on permission faults too. A VMM that maps guest memory with
PROT_MTE isn't affected, as faulting that memory into its mapping clears
the tags first. QEMU and kvmtool map it without.
I have a reproducer that reads the previous owner's tag from 511 of 512
pages in each case. With any one patch applied, it reads none in that
patch's case.
Based on Linux 7.3-rc3 (fd73f4a665989; also applies to kvmarm/next
dd0bc00e3e920 with a three-way merge).
Cheers,
/fuad
Fuad Tabba (3):
KVM: arm64: Clear the whole hugetlb folio when sanitising MTE tags
KVM: arm64: Clear the whole hugetlb folio when storing MTE tags
KVM: arm64: Sanitise MTE tags when a permission fault installs a
mapping
arch/arm64/kvm/guest.c | 11 +++++++----
arch/arm64/kvm/mmu.c | 7 ++++---
2 files changed, 11 insertions(+), 7 deletions(-)
base-commit: fd73f4a6659897191fa0d40695fe370925dd3780
--
2.47.3
^ permalink raw reply [flat|nested] 14+ messages in thread* [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-20 11:52 ` Lorenzo Stoakes (ARM) 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, 1 reply; 14+ 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] 14+ messages in thread
* Re: [PATCH 1/3] KVM: arm64: Clear the whole hugetlb folio when sanitising MTE tags 2026-10-19 13:21 ` [PATCH 1/3] KVM: arm64: Clear the whole hugetlb folio when sanitising MTE tags Fuad Tabba @ 2026-10-20 11:52 ` Lorenzo Stoakes (ARM) 2026-10-20 13:09 ` Fuad Tabba 0 siblings, 1 reply; 14+ messages in thread From: Lorenzo Stoakes (ARM) @ 2026-10-20 11:52 UTC (permalink / raw) To: Fuad Tabba Cc: Marc Zyngier, Oliver Upton, kvmarm, linux-arm-kernel, 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 hugetlb strikes again... :) the mm part of me apologises ;) On Mon, Oct 19, 2026 at 02:21:01PM +0100, Fuad Tabba wrote: > 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. I'm guessing the folio size is always >= size here? > > 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> Some nits below but generally looks sensible to me so: Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org> > --- > 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 */ Is this comment redundant now? > 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++) I know it's a stable fix, but the fact that this pattern exists in multiple places really argues for a mte_clear_folio_tags(), which would make this trivially: mte_clear_folio_tags(folio); And avoid the re-use of page etc. It's not a huge change and makes the next patch in the series simpler too so arguably could be part of the series? > mte_clear_page_tags(page_address(page)); > folio_set_hugetlb_mte_tagged(folio); > } > -- > 2.47.3 > > -- Cheers, Lorenzo ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/3] KVM: arm64: Clear the whole hugetlb folio when sanitising MTE tags 2026-10-20 11:52 ` Lorenzo Stoakes (ARM) @ 2026-10-20 13:09 ` Fuad Tabba 2026-10-20 13:16 ` Lorenzo Stoakes (ARM) 0 siblings, 1 reply; 14+ messages in thread From: Fuad Tabba @ 2026-10-20 13:09 UTC (permalink / raw) To: Lorenzo Stoakes (ARM) Cc: Marc Zyngier, Oliver Upton, kvmarm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose, Zenghui Yu, Steffen Eiden, Catalin Marinas, Will Deacon, Mark Rutland, Steven Price, Yang Shi, David Hildenbrand, linux-kernel Hi Lorenzo, On Tue, 20 Oct 2026 12:52:54 +0100, Lorenzo Stoakes (ARM) <ljs@kernel.org> wrote: [...] > On Mon, Oct 19, 2026 at 02:21:01PM +0100, Fuad Tabba wrote: > > 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. > > I'm guessing the folio size is always >= size here? Yes, the stage-2 mapping of a hugetlb VMA is never larger than its hugetlb page size, so it always sits within one folio. [...] > > diff --git 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 */ > > Is this comment redundant now? I'd keep it: it's why the whole folio has to be cleared, as the flags on the head page cover every page in it. > > 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++) > > I know it's a stable fix, but the fact that this pattern exists in multiple > places really argues for a mte_clear_folio_tags(), which would make this > trivially: > > mte_clear_folio_tags(folio); > > And avoid the re-use of page etc. > > It's not a huge change and makes the next patch in the series simpler too so > arguably could be part of the series? I think you're right about the helper, but I'd rather keep the fixes as small as possible for the backports. I'll send mte_clear_folio_tags() as a separate patch on top of these, using it in mte_sync_tags() too. In v2 the loop uses folio_page(folio, i) rather than reusing page. Thanks, /fuad ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/3] KVM: arm64: Clear the whole hugetlb folio when sanitising MTE tags 2026-10-20 13:09 ` Fuad Tabba @ 2026-10-20 13:16 ` Lorenzo Stoakes (ARM) 2026-10-20 13:22 ` Fuad Tabba 0 siblings, 1 reply; 14+ messages in thread From: Lorenzo Stoakes (ARM) @ 2026-10-20 13:16 UTC (permalink / raw) To: Fuad Tabba Cc: Marc Zyngier, Oliver Upton, kvmarm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose, Zenghui Yu, Steffen Eiden, Catalin Marinas, Will Deacon, Mark Rutland, Steven Price, Yang Shi, David Hildenbrand, linux-kernel On Tue, Oct 20, 2026 at 02:09:45PM +0100, Fuad Tabba wrote: > Hi Lorenzo, > > On Tue, 20 Oct 2026 12:52:54 +0100, Lorenzo Stoakes (ARM) > <ljs@kernel.org> wrote: > [...] > > On Mon, Oct 19, 2026 at 02:21:01PM +0100, Fuad Tabba wrote: > > > 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. > > > > I'm guessing the folio size is always >= size here? > > Yes, the stage-2 mapping of a hugetlb VMA is never larger than its > hugetlb page size, so it always sits within one folio. OK good! :) > > [...] > > > diff --git 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 */ > > > > Is this comment redundant now? > > I'd keep it: it's why the whole folio has to be cleared, as the flags > on the head page cover every page in it. OK, but there's an inconsistency between the comments in 1/3 and 2/3 (you update one in 2/3 to reflect what's happening), so maybe worth having the comment from 2/3 on both, rather than this one? (the PG_arch1,2,3 flags are folio flags unless there's something weird so it's sort of redundant I think?) > > > > 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++) > > > > I know it's a stable fix, but the fact that this pattern exists in multiple > > places really argues for a mte_clear_folio_tags(), which would make this > > trivially: > > > > mte_clear_folio_tags(folio); > > > > And avoid the re-use of page etc. > > > > It's not a huge change and makes the next patch in the series simpler too so > > arguably could be part of the series? > > I think you're right about the helper, but I'd rather keep the fixes > as small as possible for the backports. I'll send > mte_clear_folio_tags() as a separate patch on top of these, using it > in mte_sync_tags() too. In v2 the loop uses folio_page(folio, i) > rather than reusing page. Sure makes sense, though honestly I think the duplication there means delta of lines of code is small. But then again, adding a helper in a Fixes: is iffy itself so fair enough :) -- Cheers, Lorenzo ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/3] KVM: arm64: Clear the whole hugetlb folio when sanitising MTE tags 2026-10-20 13:16 ` Lorenzo Stoakes (ARM) @ 2026-10-20 13:22 ` Fuad Tabba 0 siblings, 0 replies; 14+ messages in thread From: Fuad Tabba @ 2026-10-20 13:22 UTC (permalink / raw) To: Lorenzo Stoakes (ARM) Cc: Marc Zyngier, Oliver Upton, kvmarm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose, Zenghui Yu, Steffen Eiden, Catalin Marinas, Will Deacon, Mark Rutland, Steven Price, Yang Shi, David Hildenbrand, linux-kernel On Tue, 20 Oct 2026 at 14:16, Lorenzo Stoakes (ARM) <ljs@kernel.org> wrote: [...] > > I'd keep it: it's why the whole folio has to be cleared, as the flags > > on the head page cover every page in it. > OK, but there's an inconsistency between the comments in 1/3 and 2/3 (you update > one in 2/3 to reflect what's happening), so maybe worth having the comment from > 2/3 on both, rather than this one? Sure, I'll use 2/3's wording in 1/3 for v2. Thanks! /fuad ^ permalink raw reply [flat|nested] 14+ 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-20 11:58 ` Lorenzo Stoakes (ARM) 2026-10-19 13:21 ` [PATCH 3/3] KVM: arm64: Sanitise MTE tags when a permission fault installs a mapping Fuad Tabba 2 siblings, 1 reply; 14+ 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] 14+ messages in thread
* Re: [PATCH 2/3] KVM: arm64: Clear the whole hugetlb folio when storing MTE tags 2026-10-19 13:21 ` [PATCH 2/3] KVM: arm64: Clear the whole hugetlb folio when storing " Fuad Tabba @ 2026-10-20 11:58 ` Lorenzo Stoakes (ARM) 2026-10-20 13:11 ` Fuad Tabba 0 siblings, 1 reply; 14+ messages in thread From: Lorenzo Stoakes (ARM) @ 2026-10-20 11:58 UTC (permalink / raw) To: Fuad Tabba Cc: Marc Zyngier, Oliver Upton, kvmarm, linux-arm-kernel, 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 On Mon, Oct 19, 2026 at 02:21:02PM +0100, Fuad Tabba wrote: > 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> Logic LGTM, with some nits below: Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org> > --- > 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)) Slightly awkward logic, testing a negative then the negative of the negative (i.e. else) plus folio_try_hugetlb_mte_tagging(), makes it a little harder to understand. With mte_clear_folio_tags() you can make life simpler: if (folio_test_hugetlb(folio)) { if (folio_try_hugetlb_mte_tagging(folio)) mte_clear_folio_tags(folio); } else { try_page_mte_tagging(page); } > + for (i = 0; i < folio_nr_pages(folio); i++) > + mte_clear_page_tags(page_address(folio_page(folio, i))); As above, similar comment to 1/3 re: mte_clear_folio_tags(). Would be less churn also. > num_tags = mte_copy_tags_from_user(maddr, tags, > MTE_GRANULES_PER_PAGE); > > -- > 2.47.3 > > -- Cheers, Lorenzo ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/3] KVM: arm64: Clear the whole hugetlb folio when storing MTE tags 2026-10-20 11:58 ` Lorenzo Stoakes (ARM) @ 2026-10-20 13:11 ` Fuad Tabba 2026-10-20 13:17 ` Lorenzo Stoakes (ARM) 0 siblings, 1 reply; 14+ messages in thread From: Fuad Tabba @ 2026-10-20 13:11 UTC (permalink / raw) To: Lorenzo Stoakes (ARM) Cc: Marc Zyngier, Oliver Upton, kvmarm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose, Zenghui Yu, Steffen Eiden, Catalin Marinas, Will Deacon, Mark Rutland, Steven Price, Yang Shi, David Hildenbrand, linux-kernel Hi Lorenzo, On Tue, 20 Oct 2026 12:58:13 +0100, Lorenzo Stoakes (ARM) <ljs@kernel.org> wrote: [...] > > diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c [...] > > @@ -1042,12 +1043,14 @@ int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm, [...] > > - 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)) > > Slightly awkward logic, testing a negative then the negative of the negative > (i.e. else) plus folio_try_hugetlb_mte_tagging(), makes it a little harder to > understand. > > With mte_clear_folio_tags() you can make life simpler: > > if (folio_test_hugetlb(folio)) { > if (folio_try_hugetlb_mte_tagging(folio)) > mte_clear_folio_tags(folio); > } else { > try_page_mte_tagging(page); > } Without the helper, the extra level of nesting takes the loop body past 100 columns, so I'll switch to your version in the separate patch that adds mte_clear_folio_tags() (see 1/3). Thanks, /fuad ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/3] KVM: arm64: Clear the whole hugetlb folio when storing MTE tags 2026-10-20 13:11 ` Fuad Tabba @ 2026-10-20 13:17 ` Lorenzo Stoakes (ARM) 0 siblings, 0 replies; 14+ messages in thread From: Lorenzo Stoakes (ARM) @ 2026-10-20 13:17 UTC (permalink / raw) To: Fuad Tabba Cc: Marc Zyngier, Oliver Upton, kvmarm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose, Zenghui Yu, Steffen Eiden, Catalin Marinas, Will Deacon, Mark Rutland, Steven Price, Yang Shi, David Hildenbrand, linux-kernel On Tue, Oct 20, 2026 at 02:11:11PM +0100, Fuad Tabba wrote: > > > diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c > > > @@ -1042,12 +1043,14 @@ int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm, > > > - 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)) > > > > Slightly awkward logic, testing a negative then the negative of the negative > > (i.e. else) plus folio_try_hugetlb_mte_tagging(), makes it a little harder to > > understand. > > > > With mte_clear_folio_tags() you can make life simpler: > > > > if (folio_test_hugetlb(folio)) { > > if (folio_try_hugetlb_mte_tagging(folio)) > > mte_clear_folio_tags(folio); > > } else { > > try_page_mte_tagging(page); > > } > > Without the helper, the extra level of nesting takes the loop body > past 100 columns, so I'll switch to your version in the separate patch > that adds mte_clear_folio_tags() (see 1/3). Ack makes sense, thanks! -- Cheers, Lorenzo ^ permalink raw reply [flat|nested] 14+ 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 2026-10-20 12:14 ` Lorenzo Stoakes (ARM) 2 siblings, 1 reply; 14+ 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] 14+ messages in thread
* Re: [PATCH 3/3] KVM: arm64: Sanitise MTE tags when a permission fault installs a mapping 2026-10-19 13:21 ` [PATCH 3/3] KVM: arm64: Sanitise MTE tags when a permission fault installs a mapping Fuad Tabba @ 2026-10-20 12:14 ` Lorenzo Stoakes (ARM) 2026-10-20 13:17 ` Fuad Tabba 0 siblings, 1 reply; 14+ messages in thread From: Lorenzo Stoakes (ARM) @ 2026-10-20 12:14 UTC (permalink / raw) To: Fuad Tabba Cc: Marc Zyngier, Oliver Upton, kvmarm, linux-arm-kernel, 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 On Mon, Oct 19, 2026 at 02:21:03PM +0100, Fuad Tabba wrote: > 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") Yikes! It goes quite far back :) > Cc: stable@vger.kernel.org > Signed-off-by: Fuad Tabba <fuad.tabba@linux.dev> Nits below, but with those addressed LGTM and: Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org> > --- > 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)) { OK so doing this check on permission faults too. > /* 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)) So 'translation fault or permission fault if this will install a mapping' rather than 'translation fault' alone right? Just after this code you have: if (mapping_size == perm_fault_granule) { ... } else { ... } So you could put if (!s2vi->map_non_cacheable && kvm_has_mte(kvm)) sanitise_mte_tags(kvm, pfn, mapping_size); In the else branch? Seems neater and clearer. Also I wonder if the !s2vi->map_non_cacheable && kvm_has_mte(kvm) check could be abstracted? E.g.: static bool is_mte_fault(const struct kvm *kvm, const struct kvm_s2_fault_vma_info *s2vi) { return !s2vi->map_non_cacheable && kvm_has_mte(kvm); } Then could be: if (is_mte_fault(kvm, s2vi)) sanitise_mte_tags(kvm, pfn, mapping_size); > sanitise_mte_tags(kvm, pfn, mapping_size); > > /* > -- > 2.47.3 > > -- Cheers, Lorenzo ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] KVM: arm64: Sanitise MTE tags when a permission fault installs a mapping 2026-10-20 12:14 ` Lorenzo Stoakes (ARM) @ 2026-10-20 13:17 ` Fuad Tabba 2026-10-20 13:20 ` Lorenzo Stoakes (ARM) 0 siblings, 1 reply; 14+ messages in thread From: Fuad Tabba @ 2026-10-20 13:17 UTC (permalink / raw) To: Lorenzo Stoakes (ARM) Cc: Marc Zyngier, Oliver Upton, kvmarm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose, Zenghui Yu, Steffen Eiden, Catalin Marinas, Will Deacon, Mark Rutland, Steven Price, Yang Shi, David Hildenbrand, linux-kernel Hi Lorenzo, On Tue, 20 Oct 2026 13:14:01 +0100, Lorenzo Stoakes (ARM) <ljs@kernel.org> wrote: [...] > > diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c [...] > > @@ -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)) > > So 'translation fault or permission fault if this will install a mapping' rather > than 'translation fault' alone right? Right. > Just after this code you have: > > if (mapping_size == perm_fault_granule) { > ... > } else { > ... > } > > So you could put > > if (!s2vi->map_non_cacheable && kvm_has_mte(kvm)) > sanitise_mte_tags(kvm, pfn, mapping_size); > > In the else branch? Seems neater and clearer. Agree, I'll move it there in v2. > Also I wonder if the !s2vi->map_non_cacheable && kvm_has_mte(kvm) check could be > abstracted? > > E.g.: > > static bool is_mte_fault(const struct kvm *kvm, > const struct kvm_s2_fault_vma_info *s2vi) > { > return !s2vi->map_non_cacheable && kvm_has_mte(kvm); > } > > Then could be: > > if (is_mte_fault(kvm, s2vi)) > sanitise_mte_tags(kvm, pfn, mapping_size); I'd rather leave that out: the fix doesn't change that part of the condition, and it only appears twice. Thanks, /fuad ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] KVM: arm64: Sanitise MTE tags when a permission fault installs a mapping 2026-10-20 13:17 ` Fuad Tabba @ 2026-10-20 13:20 ` Lorenzo Stoakes (ARM) 0 siblings, 0 replies; 14+ messages in thread From: Lorenzo Stoakes (ARM) @ 2026-10-20 13:20 UTC (permalink / raw) To: Fuad Tabba Cc: Marc Zyngier, Oliver Upton, kvmarm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose, Zenghui Yu, Steffen Eiden, Catalin Marinas, Will Deacon, Mark Rutland, Steven Price, Yang Shi, David Hildenbrand, linux-kernel On Tue, Oct 20, 2026 at 02:17:00PM +0100, Fuad Tabba wrote: > > In the else branch? Seems neater and clearer. > > Agree, I'll move it there in v2. Great thanks! > > if (is_mte_fault(kvm, s2vi)) > > sanitise_mte_tags(kvm, pfn, mapping_size); > > I'd rather leave that out: the fix doesn't change that part of the > condition, and it only appears twice. Ack, just a nice-to-have that. Not a big deal. -- Cheers, Lorenzo ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-10-20 13:23 UTC | newest] Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 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-20 11:52 ` Lorenzo Stoakes (ARM) 2026-10-20 13:09 ` Fuad Tabba 2026-10-20 13:16 ` Lorenzo Stoakes (ARM) 2026-10-20 13:22 ` Fuad Tabba 2026-10-19 13:21 ` [PATCH 2/3] KVM: arm64: Clear the whole hugetlb folio when storing " Fuad Tabba 2026-10-20 11:58 ` Lorenzo Stoakes (ARM) 2026-10-20 13:11 ` Fuad Tabba 2026-10-20 13:17 ` Lorenzo Stoakes (ARM) 2026-10-19 13:21 ` [PATCH 3/3] KVM: arm64: Sanitise MTE tags when a permission fault installs a mapping Fuad Tabba 2026-10-20 12:14 ` Lorenzo Stoakes (ARM) 2026-10-20 13:17 ` Fuad Tabba 2026-10-20 13:20 ` Lorenzo Stoakes (ARM)
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®