From nobody Sun Dec 14 19:14:02 2025 Received: from mail-lf1-f46.google.com (mail-lf1-f46.google.com [209.85.167.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9A5B41C005E; Fri, 28 Jun 2024 14:35:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719585341; cv=none; b=Go+6dDaNSXt1VnQ+1oocVo7m8bxKspjfPG2VkzALgKy3kMgn0cabiZ6RhYvp+QgE8sPPwx5glk2Khr6bJ8KzcPoEsdzi5cjemGxoLkEnvRFNFJj0WNYmGyLnc9F3SviXQYuWiMlpukpfopaA8RRqLwCYQMxR3hNDUDxunHI5mhE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719585341; c=relaxed/simple; bh=1r/Qu08XwERSWob4V2Z17Nm7lPY/U94sSwuNC5pDSnk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tGf3SvSeH62pMp7CI0CMk3VX4jGhRoIddZOc2mU+a5ETE98O3AZS+og2pmbKTQ1FL/+YXZXQznZrUkXdlhXudeZ//BaPE23Ifpfg55+mSXR5YxoHTJdJBqKHSFjyCzjV9SIRel5Wi9z6PnFMpFEqcqWU5inJcYv7663eC4loE5I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=N6OVWvWy; arc=none smtp.client-ip=209.85.167.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="N6OVWvWy" Received: by mail-lf1-f46.google.com with SMTP id 2adb3069b0e04-52cdd893e5cso759014e87.1; Fri, 28 Jun 2024 07:35:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1719585338; x=1720190138; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=45Fn1VR56OryxHQR2ICCsQfaXEj2VPk0P2HvHUTeh68=; b=N6OVWvWyVEVDJoWi1ntmsSk4QjPvc7s8DdbKQvQtJK1qtvYCIeXHIXhecLZCyehtXv 6abEH4Zuvx6ysKapz4xUBglUyjy//h4F64s5keFAcavEhT/QzwUmtWiMcCV5GXljPPvx 6JCc+7zQcUvR1l5K1PFpNjxurMvYV/LfFOCt5eg2bZ3L6Ir/5a9d7cC94OVDEoqJ/weZ O33v1JENAYqvif8pWDTaNnGDM8Trm12bSfFAJHY9DuAe7lFilbC8IUQ95BW07cuafTUr FsqgwsCUxhR7SmYvvC0SCcj0dfm0qVn+XCzvA1+h0iIxBGDQFLGOTyXQe728D1AZk4L3 4qeg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719585338; x=1720190138; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=45Fn1VR56OryxHQR2ICCsQfaXEj2VPk0P2HvHUTeh68=; b=W0+vj6MkEcFJe81FW4sRvnYc9xW2RolPQr+y5pV8GCQoZXjFQyfo98XPgBwrYlQYLe FEXSP5ybaZ+RkIHKQn2wpul83/AEstJFpnqM2gcA5I7oq1OnOONMxHecd5Q9UVT1EcDm 0A9Tr2vsyfJtuUuWfWhV5vk44iy4d17ov3N9g5d+XbYaidQAhWrl2VkedzxL91KNEtTl /MJYr7XV2X5zapO5XLA02gMRiyHelBflQNyBbcqz+oUUPoukjj3FH128Q82gl3van1L6 WfH5BvX5dF5A3QRapgcX2EoNm1+0kWFx6ToqkLOgXxnjS9PPcj1QmsddLjYv8Jr5GhkW mxRg== X-Forwarded-Encrypted: i=1; AJvYcCV/3pVXFwmojkYalL8AO80HFTcPM6rhDvB+bw90y3bOxMzDDsfyigs3fXx6c58kqcSoFPVualuJKKQYVU91Qa0e0ngjj+oZePfIQqD1 X-Gm-Message-State: AOJu0YwStNW3e8k7UNsg6XzvDWfn5pGrmBmoE2inj3ipdvf5TDCYWiZ9 OHRlcLrSiG8spyixMrVIpaFApVsGL7FA+5rS1wwBvPCw9DrbRLo5gwtSuw== X-Google-Smtp-Source: AGHT+IGADRofLmu0u6p9UqIYdElb/weLzHiNpcCewkVldJURTAToz8vEU+B0cUlLgs5vMRuOvfV8Zg== X-Received: by 2002:a05:6512:e95:b0:52c:898b:a180 with SMTP id 2adb3069b0e04-52ce1832725mr16276974e87.12.1719585337325; Fri, 28 Jun 2024 07:35:37 -0700 (PDT) Received: from lucifer.home ([2a00:23cc:d20f:ba01:bb66:f8b2:a0e8:6447]) by smtp.googlemail.com with ESMTPSA id 5b1f17b1804b1-4256af37828sm38985485e9.9.2024.06.28.07.35.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 28 Jun 2024 07:35:35 -0700 (PDT) From: Lorenzo Stoakes To: Andrew Morton Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, "Liam R . Howlett" , Vlastimil Babka , Matthew Wilcox , Alexander Viro , Christian Brauner , Jan Kara , Eric Biederman , Kees Cook , Suren Baghdasaryan , Lorenzo Stoakes Subject: [RFC PATCH v2 1/7] userfaultfd: move core VMA manipulation logic to mm/userfaultfd.c Date: Fri, 28 Jun 2024 15:35:22 +0100 Message-ID: <61741ce2b6c4a782ed29e3a1762047fb3c306309.1719584707.git.lstoakes@gmail.com> X-Mailer: git-send-email 2.45.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch forms part of a patch series intending to separate out VMA logic and render it testable from userspace, which requires that core manipulation functions be exposed in an mm/-internal header file. In order to do this, we must abstract APIs we wish to test, in this instance functions which ultimately invoke vma_modify(). This patch therefore moves all logic which ultimately invokes vma_modify() to mm/userfaultfd.c, trying to transfer code at a functional granularity where possible. Signed-off-by: Lorenzo Stoakes --- fs/userfaultfd.c | 160 +++----------------------------- include/linux/userfaultfd_k.h | 19 ++++ mm/userfaultfd.c | 168 ++++++++++++++++++++++++++++++++++ 3 files changed, 198 insertions(+), 149 deletions(-) diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index 17e409ceaa33..31fa788d9ecd 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -104,21 +104,6 @@ bool userfaultfd_wp_unpopulated(struct vm_area_struct = *vma) return ctx->features & UFFD_FEATURE_WP_UNPOPULATED; } =20 -static void userfaultfd_set_vm_flags(struct vm_area_struct *vma, - vm_flags_t flags) -{ - const bool uffd_wp_changed =3D (vma->vm_flags ^ flags) & VM_UFFD_WP; - - vm_flags_reset(vma, flags); - /* - * For shared mappings, we want to enable writenotify while - * userfaultfd-wp is enabled (see vma_wants_writenotify()). We'll simply - * recalculate vma->vm_page_prot whenever userfaultfd-wp changes. - */ - if ((vma->vm_flags & VM_SHARED) && uffd_wp_changed) - vma_set_page_prot(vma); -} - static int userfaultfd_wake_function(wait_queue_entry_t *wq, unsigned mode, int wake_flags, void *key) { @@ -615,22 +600,7 @@ static void userfaultfd_event_wait_completion(struct u= serfaultfd_ctx *ctx, spin_unlock_irq(&ctx->event_wqh.lock); =20 if (release_new_ctx) { - struct vm_area_struct *vma; - struct mm_struct *mm =3D release_new_ctx->mm; - VMA_ITERATOR(vmi, mm, 0); - - /* the various vma->vm_userfaultfd_ctx still points to it */ - mmap_write_lock(mm); - for_each_vma(vmi, vma) { - if (vma->vm_userfaultfd_ctx.ctx =3D=3D release_new_ctx) { - vma_start_write(vma); - vma->vm_userfaultfd_ctx =3D NULL_VM_UFFD_CTX; - userfaultfd_set_vm_flags(vma, - vma->vm_flags & ~__VM_UFFD_FLAGS); - } - } - mmap_write_unlock(mm); - + userfaultfd_release_new(release_new_ctx); userfaultfd_ctx_put(release_new_ctx); } =20 @@ -662,9 +632,7 @@ int dup_userfaultfd(struct vm_area_struct *vma, struct = list_head *fcs) return 0; =20 if (!(octx->features & UFFD_FEATURE_EVENT_FORK)) { - vma_start_write(vma); - vma->vm_userfaultfd_ctx =3D NULL_VM_UFFD_CTX; - userfaultfd_set_vm_flags(vma, vma->vm_flags & ~__VM_UFFD_FLAGS); + userfaultfd_reset_ctx(vma); return 0; } =20 @@ -749,9 +717,7 @@ void mremap_userfaultfd_prep(struct vm_area_struct *vma, up_write(&ctx->map_changing_lock); } else { /* Drop uffd context if remap feature not enabled */ - vma_start_write(vma); - vma->vm_userfaultfd_ctx =3D NULL_VM_UFFD_CTX; - userfaultfd_set_vm_flags(vma, vma->vm_flags & ~__VM_UFFD_FLAGS); + userfaultfd_reset_ctx(vma); } } =20 @@ -870,53 +836,13 @@ static int userfaultfd_release(struct inode *inode, s= truct file *file) { struct userfaultfd_ctx *ctx =3D file->private_data; struct mm_struct *mm =3D ctx->mm; - struct vm_area_struct *vma, *prev; /* len =3D=3D 0 means wake all */ struct userfaultfd_wake_range range =3D { .len =3D 0, }; - unsigned long new_flags; - VMA_ITERATOR(vmi, mm, 0); =20 WRITE_ONCE(ctx->released, true); =20 - if (!mmget_not_zero(mm)) - goto wakeup; - - /* - * Flush page faults out of all CPUs. NOTE: all page faults - * must be retried without returning VM_FAULT_SIGBUS if - * userfaultfd_ctx_get() succeeds but vma->vma_userfault_ctx - * changes while handle_userfault released the mmap_lock. So - * it's critical that released is set to true (above), before - * taking the mmap_lock for writing. - */ - mmap_write_lock(mm); - prev =3D NULL; - for_each_vma(vmi, vma) { - cond_resched(); - BUG_ON(!!vma->vm_userfaultfd_ctx.ctx ^ - !!(vma->vm_flags & __VM_UFFD_FLAGS)); - if (vma->vm_userfaultfd_ctx.ctx !=3D ctx) { - prev =3D vma; - continue; - } - /* Reset ptes for the whole vma range if wr-protected */ - if (userfaultfd_wp(vma)) - uffd_wp_range(vma, vma->vm_start, - vma->vm_end - vma->vm_start, false); - new_flags =3D vma->vm_flags & ~__VM_UFFD_FLAGS; - vma =3D vma_modify_flags_uffd(&vmi, prev, vma, vma->vm_start, - vma->vm_end, new_flags, - NULL_VM_UFFD_CTX); - - vma_start_write(vma); - userfaultfd_set_vm_flags(vma, new_flags); - vma->vm_userfaultfd_ctx =3D NULL_VM_UFFD_CTX; + userfaultfd_release_all(mm, ctx); =20 - prev =3D vma; - } - mmap_write_unlock(mm); - mmput(mm); -wakeup: /* * After no new page faults can wait on this fault_*wqh, flush * the last page faults that may have been already waiting on @@ -1293,14 +1219,14 @@ static int userfaultfd_register(struct userfaultfd_= ctx *ctx, unsigned long arg) { struct mm_struct *mm =3D ctx->mm; - struct vm_area_struct *vma, *prev, *cur; + struct vm_area_struct *vma, *cur; int ret; struct uffdio_register uffdio_register; struct uffdio_register __user *user_uffdio_register; - unsigned long vm_flags, new_flags; + unsigned long vm_flags; bool found; bool basic_ioctls; - unsigned long start, end, vma_end; + unsigned long start, end; struct vma_iterator vmi; bool wp_async =3D userfaultfd_wp_async_ctx(ctx); =20 @@ -1428,57 +1354,8 @@ static int userfaultfd_register(struct userfaultfd_c= tx *ctx, } for_each_vma_range(vmi, cur, end); BUG_ON(!found); =20 - vma_iter_set(&vmi, start); - prev =3D vma_prev(&vmi); - if (vma->vm_start < start) - prev =3D vma; - - ret =3D 0; - for_each_vma_range(vmi, vma, end) { - cond_resched(); - - BUG_ON(!vma_can_userfault(vma, vm_flags, wp_async)); - BUG_ON(vma->vm_userfaultfd_ctx.ctx && - vma->vm_userfaultfd_ctx.ctx !=3D ctx); - WARN_ON(!(vma->vm_flags & VM_MAYWRITE)); - - /* - * Nothing to do: this vma is already registered into this - * userfaultfd and with the right tracking mode too. - */ - if (vma->vm_userfaultfd_ctx.ctx =3D=3D ctx && - (vma->vm_flags & vm_flags) =3D=3D vm_flags) - goto skip; - - if (vma->vm_start > start) - start =3D vma->vm_start; - vma_end =3D min(end, vma->vm_end); - - new_flags =3D (vma->vm_flags & ~__VM_UFFD_FLAGS) | vm_flags; - vma =3D vma_modify_flags_uffd(&vmi, prev, vma, start, vma_end, - new_flags, - (struct vm_userfaultfd_ctx){ctx}); - if (IS_ERR(vma)) { - ret =3D PTR_ERR(vma); - break; - } - - /* - * In the vma_merge() successful mprotect-like case 8: - * the next vma was merged into the current one and - * the current one has not been updated yet. - */ - vma_start_write(vma); - userfaultfd_set_vm_flags(vma, new_flags); - vma->vm_userfaultfd_ctx.ctx =3D ctx; - - if (is_vm_hugetlb_page(vma) && uffd_disable_huge_pmd_share(vma)) - hugetlb_unshare_all_pmds(vma); - - skip: - prev =3D vma; - start =3D vma->vm_end; - } + ret =3D userfaultfd_register_range(ctx, vma, vm_flags, start, end, + wp_async); =20 out_unlock: mmap_write_unlock(mm); @@ -1519,7 +1396,6 @@ static int userfaultfd_unregister(struct userfaultfd_= ctx *ctx, struct vm_area_struct *vma, *prev, *cur; int ret; struct uffdio_range uffdio_unregister; - unsigned long new_flags; bool found; unsigned long start, end, vma_end; const void __user *buf =3D (void __user *)arg; @@ -1622,27 +1498,13 @@ static int userfaultfd_unregister(struct userfaultf= d_ctx *ctx, wake_userfault(vma->vm_userfaultfd_ctx.ctx, &range); } =20 - /* Reset ptes for the whole vma range if wr-protected */ - if (userfaultfd_wp(vma)) - uffd_wp_range(vma, start, vma_end - start, false); - - new_flags =3D vma->vm_flags & ~__VM_UFFD_FLAGS; - vma =3D vma_modify_flags_uffd(&vmi, prev, vma, start, vma_end, - new_flags, NULL_VM_UFFD_CTX); + vma =3D userfaultfd_clear_vma(&vmi, prev, vma, + start, vma_end); if (IS_ERR(vma)) { ret =3D PTR_ERR(vma); break; } =20 - /* - * In the vma_merge() successful mprotect-like case 8: - * the next vma was merged into the current one and - * the current one has not been updated yet. - */ - vma_start_write(vma); - userfaultfd_set_vm_flags(vma, new_flags); - vma->vm_userfaultfd_ctx =3D NULL_VM_UFFD_CTX; - skip: prev =3D vma; start =3D vma->vm_end; diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h index 05d59f74fc88..6355ed5bd34b 100644 --- a/include/linux/userfaultfd_k.h +++ b/include/linux/userfaultfd_k.h @@ -264,6 +264,25 @@ extern void userfaultfd_unmap_complete(struct mm_struc= t *mm, extern bool userfaultfd_wp_unpopulated(struct vm_area_struct *vma); extern bool userfaultfd_wp_async(struct vm_area_struct *vma); =20 +extern void userfaultfd_reset_ctx(struct vm_area_struct *vma); + +extern struct vm_area_struct *userfaultfd_clear_vma(struct vma_iterator *v= mi, + struct vm_area_struct *prev, + struct vm_area_struct *vma, + unsigned long start, + unsigned long end); + +int userfaultfd_register_range(struct userfaultfd_ctx *ctx, + struct vm_area_struct *vma, + unsigned long vm_flags, + unsigned long start, unsigned long end, + bool wp_async); + +extern void userfaultfd_release_new(struct userfaultfd_ctx *ctx); + +extern void userfaultfd_release_all(struct mm_struct *mm, + struct userfaultfd_ctx *ctx); + #else /* CONFIG_USERFAULTFD */ =20 /* mm helpers */ diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index 8dedaec00486..950fe6b2f0f7 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -1760,3 +1760,171 @@ ssize_t move_pages(struct userfaultfd_ctx *ctx, uns= igned long dst_start, VM_WARN_ON(!moved && !err); return moved ? moved : err; } + +static void userfaultfd_set_vm_flags(struct vm_area_struct *vma, + vm_flags_t flags) +{ + const bool uffd_wp_changed =3D (vma->vm_flags ^ flags) & VM_UFFD_WP; + + vm_flags_reset(vma, flags); + /* + * For shared mappings, we want to enable writenotify while + * userfaultfd-wp is enabled (see vma_wants_writenotify()). We'll simply + * recalculate vma->vm_page_prot whenever userfaultfd-wp changes. + */ + if ((vma->vm_flags & VM_SHARED) && uffd_wp_changed) + vma_set_page_prot(vma); +} + +static void userfaultfd_set_ctx(struct vm_area_struct *vma, + struct userfaultfd_ctx *ctx, + unsigned long flags) +{ + vma_start_write(vma); + vma->vm_userfaultfd_ctx =3D (struct vm_userfaultfd_ctx){ctx}; + userfaultfd_set_vm_flags(vma, + (vma->vm_flags & ~__VM_UFFD_FLAGS) | flags); +} + +void userfaultfd_reset_ctx(struct vm_area_struct *vma) +{ + userfaultfd_set_ctx(vma, NULL, 0); +} + +struct vm_area_struct *userfaultfd_clear_vma(struct vma_iterator *vmi, + struct vm_area_struct *prev, + struct vm_area_struct *vma, + unsigned long start, + unsigned long end) +{ + struct vm_area_struct *ret; + + /* Reset ptes for the whole vma range if wr-protected */ + if (userfaultfd_wp(vma)) + uffd_wp_range(vma, start, end - start, false); + + ret =3D vma_modify_flags_uffd(vmi, prev, vma, start, end, + vma->vm_flags & ~__VM_UFFD_FLAGS, + NULL_VM_UFFD_CTX); + + /* + * In the vma_merge() successful mprotect-like case 8: + * the next vma was merged into the current one and + * the current one has not been updated yet. + */ + if (!IS_ERR(ret)) + userfaultfd_reset_ctx(vma); + + return ret; +} + +/* Assumes mmap write lock taken, and mm_struct pinned. */ +int userfaultfd_register_range(struct userfaultfd_ctx *ctx, + struct vm_area_struct *vma, + unsigned long vm_flags, + unsigned long start, unsigned long end, + bool wp_async) +{ + VMA_ITERATOR(vmi, ctx->mm, start); + struct vm_area_struct *prev =3D vma_prev(&vmi); + unsigned long vma_end; + unsigned long new_flags; + + if (vma->vm_start < start) + prev =3D vma; + + for_each_vma_range(vmi, vma, end) { + cond_resched(); + + BUG_ON(!vma_can_userfault(vma, vm_flags, wp_async)); + BUG_ON(vma->vm_userfaultfd_ctx.ctx && + vma->vm_userfaultfd_ctx.ctx !=3D ctx); + WARN_ON(!(vma->vm_flags & VM_MAYWRITE)); + + /* + * Nothing to do: this vma is already registered into this + * userfaultfd and with the right tracking mode too. + */ + if (vma->vm_userfaultfd_ctx.ctx =3D=3D ctx && + (vma->vm_flags & vm_flags) =3D=3D vm_flags) + goto skip; + + if (vma->vm_start > start) + start =3D vma->vm_start; + vma_end =3D min(end, vma->vm_end); + + new_flags =3D (vma->vm_flags & ~__VM_UFFD_FLAGS) | vm_flags; + vma =3D vma_modify_flags_uffd(&vmi, prev, vma, start, vma_end, + new_flags, + (struct vm_userfaultfd_ctx){ctx}); + if (IS_ERR(vma)) + return PTR_ERR(vma); + + /* + * In the vma_merge() successful mprotect-like case 8: + * the next vma was merged into the current one and + * the current one has not been updated yet. + */ + userfaultfd_set_ctx(vma, ctx, vm_flags); + + if (is_vm_hugetlb_page(vma) && uffd_disable_huge_pmd_share(vma)) + hugetlb_unshare_all_pmds(vma); + +skip: + prev =3D vma; + start =3D vma->vm_end; + } + + return 0; +} + +void userfaultfd_release_new(struct userfaultfd_ctx *ctx) +{ + struct mm_struct *mm =3D ctx->mm; + struct vm_area_struct *vma; + VMA_ITERATOR(vmi, mm, 0); + + /* the various vma->vm_userfaultfd_ctx still points to it */ + mmap_write_lock(mm); + for_each_vma(vmi, vma) { + if (vma->vm_userfaultfd_ctx.ctx =3D=3D ctx) + userfaultfd_reset_ctx(vma); + } + mmap_write_unlock(mm); +} + +void userfaultfd_release_all(struct mm_struct *mm, + struct userfaultfd_ctx *ctx) +{ + struct vm_area_struct *vma, *prev; + VMA_ITERATOR(vmi, mm, 0); + + if (!mmget_not_zero(mm)) + return; + + /* + * Flush page faults out of all CPUs. NOTE: all page faults + * must be retried without returning VM_FAULT_SIGBUS if + * userfaultfd_ctx_get() succeeds but vma->vma_userfault_ctx + * changes while handle_userfault released the mmap_lock. So + * it's critical that released is set to true (above), before + * taking the mmap_lock for writing. + */ + mmap_write_lock(mm); + prev =3D NULL; + for_each_vma(vmi, vma) { + cond_resched(); + BUG_ON(!!vma->vm_userfaultfd_ctx.ctx ^ + !!(vma->vm_flags & __VM_UFFD_FLAGS)); + if (vma->vm_userfaultfd_ctx.ctx !=3D ctx) { + prev =3D vma; + continue; + } + + vma =3D userfaultfd_clear_vma(&vmi, prev, vma, + vma->vm_start, vma->vm_end); + prev =3D vma; + } + mmap_write_unlock(mm); + mmput(mm); +} --=20 2.45.1