From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: "David Hildenbrand (Arm)" <david@kernel.org>,
"Gregory Price (Meta)" <gourry@gourry.net>,
"Mike Rapoport (Microsoft)" <rppt@kernel.org>,
"Lorenzo Stoakes (ARM)" <ljs@kernel.org>,
Muhammad Usama Anjum <usama.anjum@arm.com>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH 6.18.y] mm/userfaultfd: wake waiters when registration modes are removed
Date: Wed, 11 Nov 2026 18:05:01 -0500 [thread overview]
Message-ID: <20261111230446.377585-1-sashal@kernel.org> (raw)
In-Reply-To: <20261109200508-failed-6.18-4eee9c389b07@kernel.org>
From: "David Hildenbrand (Arm)" <david@kernel.org>
[ Upstream commit 4eee9c389b072e161549d46dcb1ae10b0222717e ]
UFFDIO_REGISTER can replace MISSING or MINOR tracking without waking
faults that are already queued. For example, switching an anonymous
range from MISSING to WP leaves a missing-fault waiter asleep until
userspace explicitly wakes it.
When a registration change removes a UFFD mode, wake waiters in the
affected interval after updating the VMA. The VMA is write-locked at
this point, so no new faults can queue under the old modes and woken
threads cannot retry until mmap_write_unlock(). Waiters for retained
modes in the same interval may also wake and refault.
The hang reproduces for MISSING-to-WP and MINOR-to-MISSING transitions,
with both read and unread fault events.
Fixes: 63b2d4174c4a ("userfaultfd: wp: add the writeprotect API to userfaultfd ioctl")
Cc: stable@vger.kernel.org
Reviewed-by: Gregory Price (Meta) <gourry@gourry.net>
Tested-by: Gregory Price (Meta) <gourry@gourry.net>
Signed-off-by: Gregory Price (Meta) <gourry@gourry.net>
Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Tested-by: Muhammad Usama Anjum <usama.anjum@arm.com>
Link: https://patch.msgid.link/20261031-fixes_core-v3-25-d6437171ecc3@kernel.org
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
[ sashal: replaced the upstream wakeup wrapper with a direct cross-file wake_userfault() call using a shared range structure ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/userfaultfd.c | 9 ++-------
include/linux/userfaultfd_k.h | 8 ++++++++
mm/userfaultfd.c | 12 ++++++++++++
3 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index 7e40eb9131bd7..22d4a7ad54575 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -71,11 +71,6 @@ struct userfaultfd_wait_queue {
bool waken;
};
-struct userfaultfd_wake_range {
- unsigned long start;
- unsigned long len;
-};
-
/* internal indication that UFFD_API ioctl was successfully executed */
#define UFFD_FEATURE_INITIALIZED (1u << 31)
@@ -1191,8 +1186,8 @@ static void __wake_userfault(struct userfaultfd_ctx *ctx,
spin_unlock_irq(&ctx->fault_pending_wqh.lock);
}
-static __always_inline void wake_userfault(struct userfaultfd_ctx *ctx,
- struct userfaultfd_wake_range *range)
+void wake_userfault(struct userfaultfd_ctx *ctx,
+ struct userfaultfd_wake_range *range)
{
unsigned seq;
bool need_wakeup;
diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h
index 796a380664bd8..d65effb5cbff2 100644
--- a/include/linux/userfaultfd_k.h
+++ b/include/linux/userfaultfd_k.h
@@ -78,6 +78,14 @@ struct userfaultfd_ctx {
struct mm_struct *mm;
};
+struct userfaultfd_wake_range {
+ unsigned long start;
+ unsigned long len;
+};
+
+void wake_userfault(struct userfaultfd_ctx *ctx,
+ struct userfaultfd_wake_range *range);
+
extern vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason);
/* A combined operation mode + behavior flags. */
diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index 579445bddf561..5846fbf8baa09 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -2064,6 +2064,8 @@ int userfaultfd_register_range(struct userfaultfd_ctx *ctx,
prev = vma;
for_each_vma_range(vmi, vma, end) {
+ const bool any_mode_removed = vma->vm_flags & __VM_UFFD_FLAGS & ~vm_flags;
+
cond_resched();
VM_WARN_ON_ONCE(!vma_can_userfault(vma, vm_flags, wp_async));
@@ -2098,6 +2100,16 @@ int userfaultfd_register_range(struct userfaultfd_ctx *ctx,
*/
userfaultfd_set_ctx(vma, ctx, vm_flags);
+ /* Retry faults for removed modes while the VMA is write-locked. */
+ if (any_mode_removed) {
+ struct userfaultfd_wake_range range = {
+ .start = start,
+ .len = vma_end - start,
+ };
+
+ wake_userfault(ctx, &range);
+ }
+
if (is_vm_hugetlb_page(vma) && uffd_disable_huge_pmd_share(vma))
hugetlb_unshare_all_pmds(vma);
--
2.53.0
prev parent reply other threads:[~2026-11-11 23:05 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 1:05 FAILED: patch "[PATCH] mm/userfaultfd: wake waiters when registration modes are removed" failed to apply to 6.18-stable tree Sasha Levin
2026-11-11 23:05 ` Sasha Levin [this message]
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=20261111230446.377585-1-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=david@kernel.org \
--cc=gourry@gourry.net \
--cc=ljs@kernel.org \
--cc=rppt@kernel.org \
--cc=stable@vger.kernel.org \
--cc=usama.anjum@arm.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.