FAILED: patch "[PATCH] userfaultfd: prevent registration of special VMAs" failed to apply to 6.6-stable tree
Subsystems (3)
[email protected]
maintainerThe 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.
mm/userfaultfd.c +4 -1
@@ -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;
Sasha Levin
maintainerPATCH 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.
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
@@ -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
@@ -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
@@ -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
@@ -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
Sasha Levin
maintainerPATCH 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.
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
@@ -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
@@ -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
Sasha Levin
maintainerPATCH 3/3 userfaultfd: prevent registration of special VMAs
In reply to Sasha LevinFrom: "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.
--- mm/userfaultfd.c | 6 ++++++ 1 file changed, 6 insertions(+)
mm/userfaultfd.c +6 -0
@@ -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