Re: [PATCH 04/12] mm/migrate: keep the uffd bit when restoring a writable migration entry

From: Lorenzo Stoakes (ARM)

Date: Thu Nov 12 2026 - 14:14:18 EST


On Wed, Nov 11, 2026 at 12:55:12PM -0500, Tal Zussman wrote:
> remove_migration_pte() makes the restored PTE writable for a writable
> migration entry, and only looks at the uffd bit of the entry otherwise.
> A writable migration entry that has the uffd bit set is therefore
> restored as a writable PTE without the uffd bit, and the page is no
> longer write-protected.

The UFFD WP bit is such a terrible, invasive, broken piece
of... engineering :)

Notice, again, the hallmark of an utterly broken abstraction - every user
just has to happen to know to handle each of your weird edge cases every
single time they happen to interact with anything that touches it.

I do hope we never merge something as bad as this again.

>
> An entry with the uffd bit set must be restored write-protected, whether
> the entry is writable or not. remove_migration_pmd() gets this right: it

Sigh :)

> makes the PMD writable and sets the uffd bit as two independent steps,
> and pmd_mkuffd() write-protects the result. To fix it, do the same at
> the PTE level, where pte_mkuffd() write-protects the PTE as well.
>
> The only known path that created such entries is PAGEMAP_SCAN. Now that

Wait what? :)

How does a read-only scan of entries create softleaf entries?

I think this should be explained in the commit message :)

> PAGEMAP_SCAN downgrades them like change_protection() does, we should no
> longer see them, so this change alone should not be visible to
> userspace. If another path ever creates a writable migration entry with
> the uffd bit set, the page now stays write-protected instead of losing
> the uffd bit.
>
> Fixes: 52526ca7fdb9 ("fs/proc/task_mmu: implement IOCTL to get and optionally clear info about PTEs")

This seems like a super-weird fixes target.

BTW I've noticed you've not been cc'ing stable, is that on purpose? No
autosel in mm so we do need to do that on stuff intended to get backported.
:)

> Signed-off-by: Tal Zussman <tz2294@xxxxxxxxxxxx>

The change itself seems reasonable, as cursed as the reason for it is, so
with the fixes target confirmed + commit message updated:

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

> ---
> mm/migrate.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/mm/migrate.c b/mm/migrate.c
> index 28a8d7734735..d200f64b5f98 100644
> --- a/mm/migrate.c
> +++ b/mm/migrate.c
> @@ -399,7 +399,7 @@ static bool remove_migration_pte(struct folio *folio,
>
> if (softleaf_is_migration_write(entry))
> pte = pte_mkwrite(pte, vma);
> - else if (pte_swp_uffd(old_pte))
> + if (pte_swp_uffd(old_pte))
> pte = pte_mkuffd(pte);
>
> /* See do_swap_page(): restore PAGE_NONE for RWP */
>
> --
> 2.39.5
>

--
Cheers, Lorenzo