Skip to contentSkip to conversation

FAILED: patch "[PATCH] userfaultfd: prevent registration of special VMAs" failed to apply to 6.6-stable tree

PATCH New [email protected] 2 participants 4 messages Jul 29 – Aug 8

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x 3c58f641e813c3c71039f8fd4d4e2a3aab713288
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026072906-plank-status-52f6@gregkh' --subject-prefix 'PATCH 6.6.y' 'HEAD^..'

Possible dependencies:

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 3c58f641e813c3c71039f8fd4d4e2a3aab713288 Mon Sep 17 00:00:00 2001
From: "Mike Rapoport (Microsoft)" <[email protected]>
Date: Thu, 18 Jun 2026 12:50:17 +0300
Subject: [PATCH] userfaultfd: prevent registration of special VMAs

Vova Tokarev says:

userfaultfd allows registration on shadow stack VMAs. With userfaultfd access, you can register on the shadow stack, discard a page ... and inject a page with chosen return addresses via UFFDIO_COPY.

Update vma_can_userfault() to reject VM_SHADOW_STACK.

While on it, also reject VM_SPECIAL so that if a driver would implement vm_uffd_ops, it wouldn't be possible to register special VMAs with userfaultfd.

Since VM_SPECIAL includes VM_DONTEXPAND which is set but hugetlb, exclude hugetlb VMAs from the check for VM_SPECIAL.

Fixes 54007f818206 ("mm: Introduce VM_SHADOW_STACK for shadow stack memory")
Cc Al Viro <[email protected]>
Cc Christian Brauner <[email protected]>
Cc Jan Kara <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Mike Rapoport <[email protected]>
Cc Oleg Nesterov <[email protected]>
Cc Peter Xu <[email protected]>
mm/userfaultfd.c +4 -1
index 246af12bf801..c3adedaaf7d5 100644
@@ -2111,7 +2111,10 @@ static bool vma_can_userfault(struct vm_area_struct *vma, vm_flags_t vm_flags,
 {
 	const struct vm_uffd_ops *ops = vma_uffd_ops(vma);
 
-	if (vma->vm_flags & VM_DROPPABLE)
+	if (vma->vm_flags & (VM_DROPPABLE | VM_SHADOW_STACK))
+		return false;
+
+	if (!is_vm_hugetlb_page(vma) && (vma->vm_flags & VM_SPECIAL))
 		return false;
 
 	vm_flags &= __VM_UFFD_FLAGS;
maintainer
#1 lore raw

PATCH 1/3 mm: userfaultfd: add pgtable_supports_uffd_wp()

From: Chunyan Zhang <[email protected]>

[ Upstream commit f59c0924d61aa2a2bb85936a593140f327112787 ]

Some platforms can customize the PTE/PMD entry uffd-wp bit making it unavailable even if the architecture provides the resource. This patch adds a macro API pgtable_supports_uffd_wp() that allows architectures to define their specific implementations to check if the uffd-wp bit is available on which device the kernel is running.

Also this patch is removing "ifdef CONFIG_HAVE_ARCH_USERFAULTFD_WP" and "ifdef CONFIG_PTE_MARKER_UFFD_WP" in favor of pgtable_supports_uffd_wp() and uffd_supports_wp_marker() checks respectively that default to IS_ENABLED(CONFIG_HAVE_ARCH_USERFAULTFD_WP) and "IS_ENABLED(CONFIG_HAVE_ARCH_USERFAULTFD_WP) && IS_ENABLED(CONFIG_PTE_MARKER_UFFD_WP)" if not overridden by the architecture, no change in behavior is expected.

Cc Albert Ou <[email protected]>
Cc Alexandre Ghiti <[email protected]>
Cc Alexandre Ghiti <[email protected]>
Cc Al Viro <[email protected]>
Cc Andrew Jones <[email protected]>
Cc Arnd Bergmann <[email protected]>
Cc Axel Rasmussen <[email protected]>
Cc Christian Brauner <[email protected]>
Cc Conor Dooley <[email protected]>
Cc Conor Dooley <[email protected]>
Cc Deepak Gupta <[email protected]>
Cc Jan Kara <[email protected]>
Cc Liam Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Mike Rapoport <[email protected]>
Cc Palmer Dabbelt <[email protected]>
Cc Paul Walmsley <[email protected]>
Cc Peter Xu <[email protected]>
Cc Rob Herring <[email protected]>
Cc Suren Baghdasaryan <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Yuanchu Xie <[email protected]>

Stable-dep-of: 3c58f641e813 ("userfaultfd: prevent registration of special VMAs")

---
 fs/userfaultfd.c                   | 20 ++++++++++----------
 include/asm-generic/pgtable_uffd.h | 17 +++++++++++++++++
 include/linux/mm_inline.h          |  7 ++++---
 include/linux/userfaultfd_k.h      |  8 +++++---
 4 files changed, 36 insertions(+), 16 deletions(-)
fs/userfaultfd.c +10 -10
index 49f0742625981..0ebdf3c2c9ee6 100644
@@ -1354,9 +1354,9 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
 	if (uffdio_register.mode & UFFDIO_REGISTER_MODE_MISSING)
 		vm_flags |= VM_UFFD_MISSING;
 	if (uffdio_register.mode & UFFDIO_REGISTER_MODE_WP) {
-#ifndef CONFIG_HAVE_ARCH_USERFAULTFD_WP
-		goto out;
-#endif
+		if (!pgtable_supports_uffd_wp())
+			goto out;
+
 		vm_flags |= VM_UFFD_WP;
 	}
 	if (uffdio_register.mode & UFFDIO_REGISTER_MODE_MINOR) {
@@ -2068,13 +2068,13 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx,
 	uffdio_api.features &=
 		~(UFFD_FEATURE_MINOR_HUGETLBFS | UFFD_FEATURE_MINOR_SHMEM);
 #endif
-#ifndef CONFIG_HAVE_ARCH_USERFAULTFD_WP
-	uffdio_api.features &= ~UFFD_FEATURE_PAGEFAULT_FLAG_WP;
-#endif
-#ifndef CONFIG_PTE_MARKER_UFFD_WP
-	uffdio_api.features &= ~UFFD_FEATURE_WP_HUGETLBFS_SHMEM;
-	uffdio_api.features &= ~UFFD_FEATURE_WP_UNPOPULATED;
-#endif
+	if (!pgtable_supports_uffd_wp())
+		uffdio_api.features &= ~UFFD_FEATURE_PAGEFAULT_FLAG_WP;
+
+	if (!uffd_supports_wp_marker()) {
+		uffdio_api.features &= ~UFFD_FEATURE_WP_HUGETLBFS_SHMEM;
+		uffdio_api.features &= ~UFFD_FEATURE_WP_UNPOPULATED;
+	}
 
 	ret = -EINVAL;
 	if (features & ~uffdio_api.features)
include/asm-generic/pgtable_uffd.h +17 -0
index 828966d4c2811..0d85791efdf77 100644
@@ -1,6 +1,23 @@
 #ifndef _ASM_GENERIC_PGTABLE_UFFD_H
 #define _ASM_GENERIC_PGTABLE_UFFD_H
 
+/*
+ * Some platforms can customize the uffd-wp bit, making it unavailable
+ * even if the architecture provides the resource.
+ * Adding this API allows architectures to add their own checks for the
+ * devices on which the kernel is running.
+ * Note: When overriding it, please make sure the
+ * CONFIG_HAVE_ARCH_USERFAULTFD_WP is part of this macro.
+ */
+#ifndef pgtable_supports_uffd_wp
+#define pgtable_supports_uffd_wp()	IS_ENABLED(CONFIG_HAVE_ARCH_USERFAULTFD_WP)
+#endif
+
+static inline bool uffd_supports_wp_marker(void)
+{
+	return pgtable_supports_uffd_wp() && IS_ENABLED(CONFIG_PTE_MARKER_UFFD_WP);
+}
+
 #ifndef CONFIG_HAVE_ARCH_USERFAULTFD_WP
 static __always_inline int pte_uffd_wp(pte_t pte)
 {
include/linux/mm_inline.h +4 -3
index 96b1c157554c0..4fbf25c45ec91 100644
@@ -547,7 +547,6 @@ static inline pte_marker copy_pte_marker(
 
 	return dstm;
 }
-#endif
 
 /*
  * If this pte is wr-protected by uffd-wp in any form, arm the special pte to
@@ -565,9 +564,11 @@ static inline void
 pte_install_uffd_wp_if_needed(struct vm_area_struct *vma, unsigned long addr,
 			      pte_t *pte, pte_t pteval)
 {
-#ifdef CONFIG_PTE_MARKER_UFFD_WP
 	bool arm_uffd_pte = false;
 
+	if (!uffd_supports_wp_marker())
+		return;
+
 	/* The current status of the pte should be "cleared" before calling */
 	WARN_ON_ONCE(!pte_none(ptep_get(pte)));
 
@@ -594,7 +595,6 @@ pte_install_uffd_wp_if_needed(struct vm_area_struct *vma, unsigned long addr,
 	if (unlikely(arm_uffd_pte))
 		set_pte_at(vma->vm_mm, addr, pte,
 			   make_pte_marker(PTE_MARKER_UFFD_WP));
-#endif
 }
 
 static inline bool vma_has_recency(struct vm_area_struct *vma)
@@ -607,5 +607,6 @@ static inline bool vma_has_recency(struct vm_area_struct *vma)
 
 	return true;
 }
+#endif
 
 #endif
include/linux/userfaultfd_k.h +5 -3
index ac8c6854097cd..fac0f3d0deb9a 100644
@@ -166,15 +166,17 @@ static inline bool vma_can_userfault(struct vm_area_struct *vma,
 	if ((vm_flags & VM_UFFD_MINOR) &&
 	    (!is_vm_hugetlb_page(vma) && !vma_is_shmem(vma)))
 		return false;
-#ifndef CONFIG_PTE_MARKER_UFFD_WP
+
 	/*
 	 * If user requested uffd-wp but not enabled pte markers for
 	 * uffd-wp, then shmem & hugetlbfs are not supported but only
 	 * anonymous.
 	 */
-	if ((vm_flags & VM_UFFD_WP) && !vma_is_anonymous(vma))
+	if (!uffd_supports_wp_marker() && (vm_flags & VM_UFFD_WP) &&
+	    !vma_is_anonymous(vma))
 		return false;
-#endif
+
+	/* By default, allow any of anon|shmem|hugetlb */
 	return vma_is_anonymous(vma) || is_vm_hugetlb_page(vma) ||
 	    vma_is_shmem(vma);
 }
Signature · 1 line
2.53.0
maintainer
#2 lore raw

PATCH 2/3 userfaultfd: move vma_can_userfault out of line

From: "Mike Rapoport (Microsoft)" <[email protected]>

[ Upstream commit a5bb8669872b6b8463b8777a7a259a8305060016 ]

vma_can_userfault() has grown pretty big and it's not called on performance critical path.

Move it out of line.

No functional changes.

Cc Andrea Arcangeli <[email protected]>
Cc Andrei Vagin <[email protected]>
Cc Axel Rasmussen <[email protected]>
Cc Baolin Wang <[email protected]>
Cc Harry Yoo <[email protected]>
Cc Harry Yoo (Oracle) <[email protected]>
Cc Hugh Dickins <[email protected]>
Cc James Houghton <[email protected]>
Cc Lorenzo Stoakes (Oracle) <[email protected]>
Cc Matthew Wilcox (Oracle) <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Muchun Song <[email protected]>
Cc Nikita Kalyazin <[email protected]>
Cc Oscar Salvador <[email protected]>
Cc Paolo Bonzini <[email protected]>
Cc Peter Xu <[email protected]>
Cc Sean Christopherson <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Suren Baghdasaryan <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc David Carlier <[email protected]>

Stable-dep-of: 3c58f641e813 ("userfaultfd: prevent registration of special VMAs")

---
 include/linux/userfaultfd_k.h | 21 +--------------------
 mm/userfaultfd.c              | 20 ++++++++++++++++++++
 2 files changed, 21 insertions(+), 20 deletions(-)
include/linux/userfaultfd_k.h +1 -20
index fac0f3d0deb9a..67ff2889374f1 100644
@@ -160,26 +160,7 @@ static inline bool userfaultfd_armed(struct vm_area_struct *vma)
 	return vma->vm_flags & __VM_UFFD_FLAGS;
 }
 
-static inline bool vma_can_userfault(struct vm_area_struct *vma,
-				     unsigned long vm_flags)
-{
-	if ((vm_flags & VM_UFFD_MINOR) &&
-	    (!is_vm_hugetlb_page(vma) && !vma_is_shmem(vma)))
-		return false;
-
-	/*
-	 * If user requested uffd-wp but not enabled pte markers for
-	 * uffd-wp, then shmem & hugetlbfs are not supported but only
-	 * anonymous.
-	 */
-	if (!uffd_supports_wp_marker() && (vm_flags & VM_UFFD_WP) &&
-	    !vma_is_anonymous(vma))
-		return false;
-
-	/* By default, allow any of anon|shmem|hugetlb */
-	return vma_is_anonymous(vma) || is_vm_hugetlb_page(vma) ||
-	    vma_is_shmem(vma);
-}
+bool vma_can_userfault(struct vm_area_struct *vma, unsigned long vm_flags);
 
 extern int dup_userfaultfd(struct vm_area_struct *, struct list_head *);
 extern void dup_userfaultfd_complete(struct list_head *);
mm/userfaultfd.c +20 -0
index 92fe2a76f4b51..82aeaa936f019 100644
@@ -891,3 +891,23 @@ int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start,
 	mmap_read_unlock(dst_mm);
 	return err;
 }
+
+bool vma_can_userfault(struct vm_area_struct *vma, unsigned long vm_flags)
+{
+	if ((vm_flags & VM_UFFD_MINOR) &&
+	    (!is_vm_hugetlb_page(vma) && !vma_is_shmem(vma)))
+		return false;
+
+	/*
+	 * If user requested uffd-wp but not enabled pte markers for
+	 * uffd-wp, then shmem & hugetlbfs are not supported but only
+	 * anonymous.
+	 */
+	if (!uffd_supports_wp_marker() && (vm_flags & VM_UFFD_WP) &&
+	    !vma_is_anonymous(vma))
+		return false;
+
+	/* By default, allow any of anon|shmem|hugetlb */
+	return vma_is_anonymous(vma) || is_vm_hugetlb_page(vma) ||
+	    vma_is_shmem(vma);
+}
Signature · 1 line
2.53.0
maintainer
#3 lore raw

PATCH 3/3 userfaultfd: prevent registration of special VMAs

In reply to Sasha Levin

From: "Mike Rapoport (Microsoft)" <[email protected]>

[ Upstream commit 3c58f641e813c3c71039f8fd4d4e2a3aab713288 ]

Vova Tokarev says:

userfaultfd allows registration on shadow stack VMAs. With userfaultfd access, you can register on the shadow stack, discard a page ... and inject a page with chosen return addresses via UFFDIO_COPY.

Update vma_can_userfault() to reject VM_SHADOW_STACK.

While on it, also reject VM_SPECIAL so that if a driver would implement vm_uffd_ops, it wouldn't be possible to register special VMAs with userfaultfd.

Since VM_SPECIAL includes VM_DONTEXPAND which is set but hugetlb, exclude hugetlb VMAs from the check for VM_SPECIAL.

Fixes 54007f818206 ("mm: Introduce VM_SHADOW_STACK for shadow stack memory")
Cc Al Viro <[email protected]>
Cc Christian Brauner <[email protected]>
Cc Jan Kara <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Mike Rapoport <[email protected]>
Cc Oleg Nesterov <[email protected]>
Cc Peter Xu <[email protected]>
---
 mm/userfaultfd.c | 6 ++++++
 1 file changed, 6 insertions(+)
mm/userfaultfd.c +6 -0
index 82aeaa936f019..99438f0950e3c 100644
@@ -894,6 +894,12 @@ int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start,
 
 bool vma_can_userfault(struct vm_area_struct *vma, unsigned long vm_flags)
 {
+	if (vma->vm_flags & VM_SHADOW_STACK)
+		return false;
+
+	if (!is_vm_hugetlb_page(vma) && (vma->vm_flags & VM_SPECIAL))
+		return false;
+
 	if ((vm_flags & VM_UFFD_MINOR) &&
 	    (!is_vm_hugetlb_page(vma) && !vma_is_shmem(vma)))
 		return false;
Signature · 1 line
2.53.0