From: "Lorenzo Stoakes (ARM)" <ljs@kernel.org>
To: Tal Zussman <tz2294@columbia.edu>
Cc: "Andrew Morton" <akpm@linux-foundation.org>,
"Mike Rapoport" <rppt@kernel.org>, "Peter Xu" <peterx@redhat.com>,
"James Houghton" <jthoughton@google.com>,
"Andrea Arcangeli" <aarcange@redhat.com>,
"Suren Baghdasaryan" <surenb@google.com>,
"Balbir Singh" <balbirs@nvidia.com>,
"Liam R. Howlett" <liam@infradead.org>,
"Vlastimil Babka" <vbabka@kernel.org>,
"Jann Horn" <jannh@google.com>,
"Pedro Falcato" <pfalcato@suse.de>,
"Michał Mirosław" <mirq-linux@rere.qmqm.pl>,
"Andrei Vagin" <avagin@gmail.com>,
"Stephen Rothwell" <sfr@canb.auug.org.au>,
"Arnd Bergmann" <arnd@arndb.de>,
"Muhammad Usama Anjum" <usama.anjum@arm.com>,
"David Hildenbrand" <david@kernel.org>, "Zi Yan" <ziy@nvidia.com>,
"Matthew Brost" <matthew.brost@intel.com>,
"Joshua Hahn" <joshua.hahnjy@gmail.com>,
"Byungchul Park" <byungchul@sk.com>,
"Gregory Price" <gourry@gourry.net>,
"Ying Huang" <ying.huang@linux.alibaba.com>,
"Alistair Popple" <apopple@nvidia.com>,
"Baolin Wang" <baolin.wang@linux.alibaba.com>,
"Nico Pache" <nico.pache@linux.dev>,
"Ryan Roberts" <ryan.roberts@arm.com>,
"Dev Jain" <dev.jain@arm.com>, "Barry Song" <baohua@kernel.org>,
"Lance Yang" <lance.yang@linux.dev>,
"Usama Arif" <usama.arif@linux.dev>,
"Kiryl Shutsemau" <kas@kernel.org>,
"Chris Down" <chris@chrisdown.name>,
"Muchun Song" <muchun.song@linux.dev>,
"Oscar Salvador" <osalvador@suse.de>,
"Mikołaj Lenczewski" <miko.lenczewski@arm.com>,
"Michal Hocko" <mhocko@suse.com>,
"Mike Kravetz" <mike.kravetz@oracle.com>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
linux-fsdevel@vger.kernel.org
Subject: Re: [PATCH 03/12] fs/proc/task_mmu: downgrade writable migration entries in PAGEMAP_SCAN write-protect
Date: Thu, 12 Nov 2026 18:34:05 +0000 [thread overview]
Message-ID: <avYApSoRMz7IZSox@gremlin> (raw)
In-Reply-To: <20261111-uffd-state-fixes-v1-3-00713d368976@columbia.edu>
On Wed, Nov 11, 2026 at 12:55:11PM -0500, Tal Zussman wrote:
> PAGEMAP_SCAN with PM_SCAN_WP_MATCHING write-protects pages in a VMA
> registered for async uffd-wp, and sets the uffd bit on non-present
> entries as they are. An entry with the uffd bit set must not be
> writable, so that the page is write-protected once it is mapped again.
> change_protection() therefore downgrades writable migration and
> device-private entries to readable ones first, but PAGEMAP_SCAN does
> not.
>
> For a writable migration entry at the PTE level,
> remove_migration_pte() restores a writable PTE without the uffd bit. So
> if a page is under migration while PAGEMAP_SCAN write-protects it, the
> write protection is lost. A user tracking writes with async uffd-wp
> sees the page reported as written on the next scan although nothing
> wrote to it.
>
> With CONFIG_PAGE_TABLE_CHECK, setting the uffd bit on a writable
> non-present PTE or PMD also triggers a warning.
>
> To fix it, downgrade writable migration and device-private entries
> before setting the uffd bit, as change_protection() does, at the PTE,
> PMD, and hugetlb levels.
>
> Fixes: 52526ca7fdb9 ("fs/proc/task_mmu: implement IOCTL to get and optionally clear info about PTEs")
> Signed-off-by: Tal Zussman <tz2294@columbia.edu>
> ---
> fs/proc/task_mmu.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 51 insertions(+), 3 deletions(-)
>
> diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
> index 22361607020d..53780a454432 100644
> --- a/fs/proc/task_mmu.c
> +++ b/fs/proc/task_mmu.c
> @@ -2395,6 +2395,38 @@ static unsigned long pagemap_page_category(struct pagemap_scan_private *p,
> return categories;
> }
>
> +/* Downgrade a writable migration or device-private entry to a readable one. */
> +static softleaf_t make_readable_softleaf(softleaf_t entry)
> +{
> + if (softleaf_is_device_private_write(entry))
> + return make_readable_device_private_entry(swp_offset(entry));
> + if (!softleaf_is_migration_write(entry))
> + return entry;
> + if (folio_test_anon(softleaf_to_folio(entry)))
Hmm _seems_ a bit dubious. You identify a readable exclusive migration entry by
checking whether its folio is anon?
But I guess because a writable migration entry can only come from a writable
PTE, that implies anonexclusive. But you do need to explicitly say that.
Also we really do have to break this out as a helper. I see it's open coded in
change_softleaf_pte(), change_non_present_huge_pmd() and
hugetlb_change_protection().
But maybe that can be a follow up...
> + return make_readable_exclusive_migration_entry(swp_offset(entry));
> + return make_readable_migration_entry(swp_offset(entry));
This is all super compressed.
I'd say add to leafops.h but break it up:
static inline softleaf_t softleaf_migration_mkreadable(softleaf_t entry)
{
const pgoff_t offset = swp_offset(entry);
VM_WARN_ON_ONCE(!softleaf_is_migration_write(entry));
/* A writable anon migration entry implies AnonExclusive. */
if (folio_test_anon(softleaf_to_folio(entry)))
return make_readable_exclusive_migration_entry(offset);
return make_readable_migration_entry(offset);
}
static inline softleaf_t softleaf_mkreadable(softleaf_t entry)
{
switch (softleaf_type(entry)) {
case SOFTLEAF_DEVICE_PRIVATE_WRITE:
return make_readable_device_private_entry(swp_offset(entry));
case SOFTLEAF_MIGRATION_WRITE:
return softleaf_migration_mkreadable(entry);
default:
return entry;
}
}
> +}
> +
> +/*
> + * An armed entry must not come back writable, so downgrade a writable
> + * migration or device-private entry before giving it the bit, as
> + * change_softleaf_pte() does.
> + */
> +static pte_t set_uffd_wp_swp_pte(pte_t pte)
This is a contradictory name, you're interacting with softleaves, there's no such
thing as a uffd swap entry :)
I/we obviously have to go and fixup the naming (I didn't _quite_ finish the
softleaf conversions I guess) but let's not propagate it.
> +{
> + softleaf_t entry = softleaf_from_pte(pte);
> + pte_t newpte;
> +
> + if (!softleaf_is_migration_write(entry) &&
> + !softleaf_is_device_private_write(entry))
> + return pte_swp_mkuffd(pte);
> +
> + newpte = softleaf_to_pte(make_readable_softleaf(entry));
> + if (pte_swp_soft_dirty(pte))
> + newpte = pte_swp_mksoft_dirty(newpte);
> + return pte_swp_mkuffd(newpte);
> +}
> +
> static void make_uffd_wp_pte(struct vm_area_struct *vma,
> unsigned long addr, pte_t *pte, pte_t ptent)
> {
> @@ -2408,7 +2440,7 @@ static void make_uffd_wp_pte(struct vm_area_struct *vma,
> set_pte_at(vma->vm_mm, addr, pte,
> make_pte_marker(PTE_MARKER_UFFD_WP));
> } else {
> - ptent = pte_swp_mkuffd(ptent);
> + ptent = set_uffd_wp_swp_pte(ptent);
> set_pte_at(vma->vm_mm, addr, pte, ptent);
> }
> }
> @@ -2467,6 +2499,22 @@ static unsigned long pagemap_thp_category(struct pagemap_scan_private *p,
> return categories;
> }
>
> +/* Same as set_uffd_wp_swp_pte(), for a non-present PMD. */
No need to say non-present. Naming it with 'softleaf' somewhere in there implies
that. E.g. set_u
> +static pmd_t set_uffd_wp_swp_pmd(pmd_t pmd)
Same comment here, this is just hugely confusing.
> +{
> + softleaf_t entry = softleaf_from_pmd(pmd);
> + pmd_t newpmd;
> +
> + if (!softleaf_is_migration_write(entry) &&
> + !softleaf_is_device_private_write(entry))
> + return pmd_swp_mkuffd(pmd);
> +
> + newpmd = softleaf_to_pmd(make_readable_softleaf(entry));
> + if (pmd_swp_soft_dirty(pmd))
> + newpmd = pmd_swp_mksoft_dirty(newpmd);
> + return pmd_swp_mkuffd(newpmd);
> +}
> +
> static void make_uffd_wp_pmd(struct vm_area_struct *vma,
> unsigned long addr, pmd_t *pmdp)
> {
> @@ -2477,7 +2525,7 @@ static void make_uffd_wp_pmd(struct vm_area_struct *vma,
> pmd = pmd_mkuffd(old);
> set_pmd_at(vma->vm_mm, addr, pmdp, pmd);
> } else if (pmd_is_migration_entry(pmd)) {
> - pmd = pmd_swp_mkuffd(pmd);
> + pmd = set_uffd_wp_swp_pmd(pmd);
> set_pmd_at(vma->vm_mm, addr, pmdp, pmd);
> }
> }
> @@ -2547,7 +2595,7 @@ static void make_uffd_wp_huge_pte(struct vm_area_struct *vma,
>
> if (softleaf_is_migration(entry)) {
> set_huge_pte_at(vma->vm_mm, addr, ptep,
> - pte_swp_mkuffd(ptent), psize);
> + set_uffd_wp_swp_pte(ptent), psize);
> } else {
> pte_t old_pte, new_pte;
>
>
> --
> 2.39.5
>
--
Cheers, Lorenzo
next prev parent reply other threads:[~2026-11-12 18:34 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-11 17:55 [PATCH 00/12] userfaultfd: assorted fixes (part 1) Tal Zussman
2026-11-11 17:55 ` [PATCH 01/12] userfaultfd: use anonymous memory for UFFDIO_ZEROPAGE on private file mappings Tal Zussman
2026-11-12 18:05 ` Lorenzo Stoakes (ARM)
2026-11-11 17:55 ` [PATCH 02/12] userfaultfd: refuse UFFDIO_MOVE into a non-present huge destination PMD Tal Zussman
2026-11-12 17:56 ` sashiko-bot
2026-11-12 18:07 ` Lorenzo Stoakes (ARM)
2026-11-11 17:55 ` [PATCH 03/12] fs/proc/task_mmu: downgrade writable migration entries in PAGEMAP_SCAN write-protect Tal Zussman
2026-11-12 18:34 ` Lorenzo Stoakes (ARM) [this message]
2026-11-11 17:55 ` [PATCH 04/12] mm/migrate: keep the uffd bit when restoring a writable migration entry Tal Zussman
2026-11-12 18:44 ` Lorenzo Stoakes (ARM)
2026-11-11 17:55 ` [PATCH 05/12] fs/proc/task_mmu: write-protect device-private THPs in PAGEMAP_SCAN Tal Zussman
2026-11-12 19:34 ` Lorenzo Stoakes (ARM)
2026-11-11 17:55 ` [PATCH 06/12] mm/huge_memory: build the moved huge zero PMD from the destination VMA Tal Zussman
2026-11-11 19:12 ` Kiryl Shutsemau
2026-11-12 17:57 ` sashiko-bot
2026-11-11 17:55 ` [PATCH 07/12] mm/mremap: resolve uffd state when the context is dropped, not during the move Tal Zussman
2026-11-11 19:20 ` Kiryl Shutsemau
2026-11-11 22:39 ` Tal Zussman
2026-11-12 11:44 ` Lorenzo Stoakes (ARM)
2026-11-12 16:00 ` Tal Zussman
2026-11-12 17:57 ` sashiko-bot
2026-11-11 17:55 ` [PATCH 08/12] mm/migrate_device: do not migrate a uffd-protected zero page Tal Zussman
2026-11-11 17:55 ` [PATCH 09/12] mm/madvise: let a guard marker carry the uffd-wp bit Tal Zussman
2026-11-12 11:21 ` Lorenzo Stoakes (ARM)
2026-11-12 16:06 ` Tal Zussman
2026-11-11 17:55 ` [PATCH 10/12] mm: set the uffd-wp bit on a guard marker when write-protecting Tal Zussman
2026-11-12 11:43 ` Lorenzo Stoakes (ARM)
2026-11-11 17:55 ` [PATCH 11/12] mm/madvise: send UFFD_EVENT_REMOVE when installing guard regions Tal Zussman
2026-11-11 19:25 ` Kiryl Shutsemau
2026-11-11 23:21 ` Tal Zussman
2026-11-12 9:40 ` Jose A. Perez de Azpillaga
2026-11-12 11:57 ` Kiryl Shutsemau
2026-11-12 11:03 ` Lorenzo Stoakes (ARM)
2026-11-12 11:06 ` Lorenzo Stoakes (ARM)
2026-11-12 15:56 ` Tal Zussman
2026-11-12 17:57 ` sashiko-bot
2026-11-11 17:55 ` [PATCH 12/12] mm/userfaultfd: check hugetlb end alignment in UFFDIO_UNREGISTER pre-scan Tal Zussman
2026-11-12 19:52 ` Lorenzo Stoakes (ARM)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=avYApSoRMz7IZSox@gremlin \
--to=ljs@kernel.org \
--cc=aarcange@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=apopple@nvidia.com \
--cc=arnd@arndb.de \
--cc=avagin@gmail.com \
--cc=balbirs@nvidia.com \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=byungchul@sk.com \
--cc=chris@chrisdown.name \
--cc=david@kernel.org \
--cc=dev.jain@arm.com \
--cc=gourry@gourry.net \
--cc=jannh@google.com \
--cc=joshua.hahnjy@gmail.com \
--cc=jthoughton@google.com \
--cc=kas@kernel.org \
--cc=lance.yang@linux.dev \
--cc=liam@infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=matthew.brost@intel.com \
--cc=mhocko@suse.com \
--cc=mike.kravetz@oracle.com \
--cc=miko.lenczewski@arm.com \
--cc=mirq-linux@rere.qmqm.pl \
--cc=muchun.song@linux.dev \
--cc=nico.pache@linux.dev \
--cc=osalvador@suse.de \
--cc=peterx@redhat.com \
--cc=pfalcato@suse.de \
--cc=rppt@kernel.org \
--cc=ryan.roberts@arm.com \
--cc=sfr@canb.auug.org.au \
--cc=surenb@google.com \
--cc=tz2294@columbia.edu \
--cc=usama.anjum@arm.com \
--cc=usama.arif@linux.dev \
--cc=vbabka@kernel.org \
--cc=ying.huang@linux.alibaba.com \
--cc=ziy@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.