Re: [PATCH 07/10] mm/hugetlb: tolerate uffd bits set without uffd for PROT_NONE PTEs

From: Lorenzo Stoakes (ARM)

Date: Thu Oct 15 2026 - 16:25:02 EST


On Thu, Oct 15, 2026 at 06:07:13PM +0200, David Hildenbrand (Arm) wrote:
> The whole uffd handling when a VMA is unregistered from UFFD is shaky:
> there are still some scenarios where we might have stale uffd PTE bits
> in VMAs no longer registered for UFFD, which confuses other code.
>
> Let's just tolerate that for now and simply clear the PTE bit. Add a
> TODO to really clean up any uffd leftovers when unregistering a VMA from
> userfaultfd.
>
> The handling is now more similar to what we have in handle_pte_fault().
>
> Fixes: 2d427bb01639 ("mm/userfaultfd: add RWP fault delivery and expose UFFDIO_REGISTER_MODE_RWP")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: David Hildenbrand (Arm) <david@xxxxxxxxxx>

Ugh what a mess. It seems like bad code makes any edits going forward
problematic because of the labyrinth of bailing wire and chewing gum left
behind.

Anyway seems sensible to me so:

Acked-by: Lorenzo Stoakes (ARM) <ljs@xxxxxxxxxx>

> ---
> mm/hugetlb.c | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index c3823f1958568..ba6860b9b7f4c 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -6127,16 +6127,20 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
> * NUMA hinting), so let normal hugetlb fault handling proceed.
> */
> if (pte_protnone(vmf.orig_pte) && vma_is_accessible(vma) &&
> - userfaultfd_rwp(vma) && huge_pte_uffd(vmf.orig_pte)) {
> + huge_pte_uffd(vmf.orig_pte)) {
> spinlock_t *ptl;
> pte_t pte;
>
> /* Sync: drop hugetlb locks before blocking in handle_userfault() */
> - if (!userfaultfd_rwp_async(vma))
> + if (userfaultfd_rwp(vma) && !userfaultfd_rwp_async(vma))
> return hugetlb_handle_userfault(&vmf, mapping, VM_UFFD_RWP);
>
> ptl = huge_pte_lock(h, mm, vmf.pte);
> pte = huge_ptep_get(mm, vmf.address, vmf.pte);
> + /*
> + * TODO: fix all cases where uffd PTE bits remain in VMAs that
> + * are no longer registered with uffd.
> + */
> if (pte_protnone(pte) && huge_pte_uffd(pte)) {
> unsigned int shift = huge_page_shift(h);
>
>
> --
> 2.43.0
>

--
Cheers, Lorenzo