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 09/12] mm/madvise: let a guard marker carry the uffd-wp bit
Date: Thu, 12 Nov 2026 11:21:24 +0000 [thread overview]
Message-ID: <avWeNRMIU2QPGZ4w@gremlin> (raw)
In-Reply-To: <20261111-uffd-state-fixes-v1-9-00713d368976@columbia.edu>
On Wed, Nov 11, 2026 at 12:55:17PM -0500, Tal Zussman wrote:
> MADV_GUARD_INSTALL can only install guard markers in a range without
> populated entries. It zaps the range and retries, restarting the syscall
> if the range still isn't clear. On a file-backed VMA registered for
> uffd-wp, the zap keeps uffd-wp markers and converts write-protected PTEs
> into new markers, as the pages are still in the page cache and must stay
> write-protected. The range never becomes clear, and installing a guard
> region in write-protected shmem keeps restarting the madvise() call.
> Signal handlers still run, but the call does not return until the task
> is killed.
>
> An entry that is write-protected must stay write-protected while a guard
> is installed on it and after the guard is removed. PTE markers are a bit
> mask, so a marker can be a guard marker and a uffd-wp marker at the same
> time. To fix it, let a guard marker carry the uffd-wp bit:
>
> - guard install adds the guard bit to an existing uffd-wp marker
> - guard removal clears only the guard bit
> - unprotecting or unregistering clears the uffd-wp bit of a guard
> marker
>
> The fault path, zap, fork, and pagemap already handle a marker with both
> bits set. However, pte_is_uffd_marker() would let UFFDIO_COPY overwrite
> the guard, so make it ignore guard markers. Anonymous VMAs drop uffd-wp
> markers on zap and never get the combined marker.
>
> MADV_GUARD_INSTALL on a uffd-wp shmem range now succeeds instead of
> hanging. When the guard region is removed again, its pages are still
> write-protected. While the guard is in place, pagemap reports both
> PM_GUARD_REGION and PM_UFFD_WP for them.
>
> There are two simpler alternatives, but neither works. Zapping with
> ZAP_FLAG_DROP_MARKER fixes the hang but drops the write protection: the
> page is still in the page cache once the guard is removed, and writes to
> it are not reported. Refusing guard install on uffd-wp file VMAs in
> is_valid_guard_vma() would break a combination that works on anonymous
> memory, by adding a new -EINVAL for it.
>
> Fixes: f807123d578d ("mm: allow guard regions in file-backed and read-only mappings")
> Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Please drop this patch too.
With my patch disallowing guard marker install on uffd-armed VMAs this goes
away (and doesn't make sense anyway.)
I really feel these guard region ones should have been sent separately, btw.
You're establishing a bunch of interlocking dependencies of different changes in
this series that makes life hard for reviewers, especially given backports etc.
And now I'm having to essentially inverse cherry pick stuff :)
> ---
> include/linux/leafops.h | 4 ++++
> mm/madvise.c | 28 ++++++++++++++++++++++++++--
> mm/mprotect.c | 23 +++++++++++++++++++++--
> 3 files changed, 51 insertions(+), 4 deletions(-)
>
> diff --git a/include/linux/leafops.h b/include/linux/leafops.h
> index 4c1476ae3234..add4968ded44 100644
> --- a/include/linux/leafops.h
> +++ b/include/linux/leafops.h
> @@ -578,6 +578,10 @@ static inline bool pte_is_uffd_marker(pte_t pte)
> if (!softleaf_is_marker(entry))
> return false;
>
> + /* A guard marker stays a guard, even with the uffd-wp bit set. */
> + if (softleaf_is_guard_marker(entry))
> + return false;
> +
> /* UFFD WP, poisoned swap entries are UFFD-handled. */
> if (softleaf_is_uffd_wp_marker(entry))
> return true;
> diff --git a/mm/madvise.c b/mm/madvise.c
> index 0214efd2a014..e2c6b0f26672 100644
> --- a/mm/madvise.c
> +++ b/mm/madvise.c
> @@ -1123,6 +1123,23 @@ static int guard_install_pte_entry(pte_t *pte, unsigned long addr,
> return 0;
> }
>
> + /*
> + * Zapping keeps uffd-wp markers on file-backed VMAs, so add the guard
> + * to the marker instead. The slot stays write-protected once the guard
> + * is removed.
> + */
> + if (!vma_is_anonymous(walk->vma) && pte_is_uffd_wp_marker(pteval)) {
> + const softleaf_t entry = softleaf_from_pte(pteval);
> +
> + set_pte_at(walk->mm, addr, pte,
> + make_pte_marker(softleaf_to_marker(entry) |
> + PTE_MARKER_GUARD));
> + update_mmu_cache(walk->vma, addr, pte);
> + (*nr_pages)++;
> +
> + return 0;
> + }
> +
> /* If populated return >0 so we abort the operation + zap. */
> return 1;
> }
> @@ -1259,8 +1276,15 @@ static int guard_remove_pte_entry(pte_t *pte, unsigned long addr,
> pte_t ptent = ptep_get(pte);
>
> if (is_guard_pte_marker(ptent)) {
> - /* Simply clear the PTE marker. */
> - pte_clear(walk->mm, addr, pte);
> + const softleaf_t entry = softleaf_from_pte(ptent);
> + const pte_marker marker = softleaf_to_marker(entry) &
> + ~PTE_MARKER_GUARD;
> +
> + /* Clear the guard bit and keep the uffd-wp bit, if set. */
> + if (marker)
> + set_pte_at(walk->mm, addr, pte, make_pte_marker(marker));
> + else
> + pte_clear(walk->mm, addr, pte);
> update_mmu_cache(walk->vma, addr, pte);
> }
>
> diff --git a/mm/mprotect.c b/mm/mprotect.c
> index ef4e7188e24d..6cc5b99b4185 100644
> --- a/mm/mprotect.c
> +++ b/mm/mprotect.c
> @@ -249,9 +249,28 @@ static long change_softleaf_pte(struct vm_area_struct *vma,
> * because any access should sigbus/sigsegv
> * anyway.
> */
> - if (softleaf_is_poison_marker(entry) ||
> - softleaf_is_guard_marker(entry))
> + if (softleaf_is_poison_marker(entry))
> return 0;
> +
> + /*
> + * A guard marker on a file-backed VMA carries the
> + * uffd-wp state of the slot for when the guard is
> + * removed.
> + */
> + if (softleaf_is_guard_marker(entry)) {
> + const pte_marker old = softleaf_to_marker(entry);
> + pte_marker marker = old;
> +
> + if (uffd_prot_resolve)
> + marker &= ~PTE_MARKER_UFFD_WP;
> +
> + if (marker == old)
> + return 0;
> + set_pte_at(vma->vm_mm, addr, pte,
> + make_pte_marker(marker));
> + return 1;
> + }
> +
> /*
> * If this is uffd-wp pte marker and we'd like
> * to unprotect it, drop it; the next page
>
> --
> 2.39.5
>
--
Cheers, Lorenzo
next prev parent reply other threads:[~2026-11-12 11:21 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)
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) [this message]
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=avWeNRMIU2QPGZ4w@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.