[PATCH v2 24/47] mm/userfaultfd: wake all waiters on unregister
From: David Hildenbrand (Arm)
Date: Thu Oct 29 2026 - 16:39:50 EST
From: Josef Bacik <josef@xxxxxxxxxxxxxx>
UFFDIO_UNREGISTER only wakes pending faults if VM_UFFD_MISSING is set.
Threads waiting on write-protect, minor or RWP faults can therefore remain
asleep after unregistering a range that does not track missing faults.
Wake pending faults regardless of the registration mode so they can retry
without an explicit UFFDIO_WAKE or closing the userfaultfd. This matches
the existing behavior for missing faults, including removing unread fault
messages for the woken waiters.
Fix generated by an LLM and sent by Josef Bacik in private.
Fixes: 63b2d4174c4a ("userfaultfd: wp: add the writeprotect API to userfaultfd ioctl")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
[ david: rebase; simplify description ]
Reviewed-by: Mike Rapoport (Microsoft) <rppt@xxxxxxxxxx>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@xxxxxxxxxx>
Signed-off-by: David Hildenbrand (Arm) <david@xxxxxxxxxx>
---
mm/userfaultfd.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index 3ca04b582329..be630674fda9 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -3977,6 +3977,8 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
ret = 0;
for_each_vma_range(vmi, vma, end) {
+ struct userfaultfd_wake_range range;
+
cond_resched();
/* VMA not registered with userfaultfd. */
@@ -3994,18 +3996,14 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
/* Prevent new userfaults from being queued after the wakeup. */
vma_start_write(vma);
- if (userfaultfd_missing(vma)) {
- /*
- * Wake any concurrent pending userfault while
- * we unregister, so they will not hang
- * permanently and it avoids userland to call
- * UFFDIO_WAKE explicitly.
- */
- struct userfaultfd_wake_range range;
- range.start = start;
- range.len = vma_end - start;
- wake_userfault(vma->vm_userfaultfd_ctx.ctx, &range);
- }
+ /*
+ * Wake any concurrent pending userfault while we unregister,
+ * so they will not hang permanently and it avoids userland to
+ * call UFFDIO_WAKE explicitly.
+ */
+ range.start = start;
+ range.len = vma_end - start;
+ wake_userfault(ctx, &range);
vma = userfaultfd_clear_vma(&vmi, prev, vma,
start, vma_end);
--
2.43.0