FAILED: patch "[PATCH] userfaultfd: prevent registration of special VMAs" failed to apply to 6.12-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.12-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.12.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-scheming-vocation-25cd@gregkh' --subject-prefix 'PATCH 6.12.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/2 mm/khugepaged: guard is_zero_pfn() calls with pte_present()
From: Lance Yang <[email protected]>
[ Upstream commit 074f027d15c10cb376b3ad88405b8e512fa5b3a8 ]
A non-present entry, like a swap PTE, contains completely different data (swap type and offset). pte_pfn() doesn't know this, so if we feed it a non-present entry, it will spit out a junk PFN.
What if that junk PFN happens to match the zeropage's PFN by sheer chance? While really unlikely, this would be really bad if it did.
So, let's fix this potential bug by ensuring all calls to is_zero_pfn() in khugepaged.c are properly guarded by a pte_present() check.
Stable-dep-of: 3c58f641e813 ("userfaultfd: prevent registration of special VMAs")
--- mm/khugepaged.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-)
mm/khugepaged.c +21 -14
@@ -346,6 +346,13 @@ struct attribute_group khugepaged_attr_group = { };#endif /* CONFIG_SYSFS */ +static bool pte_none_or_zero (pte_t pte) +{ +if (pte_none (pte)) +return true; +return pte_present (pte) &&is_zero_pfn (pte_pfn (pte)); +} +int hugepage_madvise (struct vm_area_struct *vma,unsigned long *vm_flags,int advice) {
@@ -529,6 +536,7 @@ static void release_pte_pages(pte_t *pte, pte_t *_pte,if (pte_none (pteval))continue ; +VM_WARN_ON_ONCE (!pte_present (pteval)); pfn =pte_pfn (pteval);if (is_zero_pfn (pfn))continue ;
@@ -572,8 +580,7 @@ static int __collapse_huge_page_isolate(struct vm_area_struct *vma,for (_pte = pte; _pte < pte +HPAGE_PMD_NR ; _pte++, address +=PAGE_SIZE ) {pte_t pteval =ptep_get (_pte); -if (pte_none (pteval) || (pte_present (pteval) && -is_zero_pfn (pte_pfn (pteval)))) { +if (pte_none_or_zero (pteval)) { ++none_or_zero; if (!userfaultfd_armed(vma) && (!cc->is_khugepaged ||
@@ -716,17 +723,17 @@ static void __collapse_huge_page_copy_succeeded(pte_t *pte,for (_pte = pte; _pte < pte +HPAGE_PMD_NR ; _pte++, address +=PAGE_SIZE ) { pteval =ptep_get (_pte); -if (pte_none (pteval) ||is_zero_pfn (pte_pfn (pteval))) { +if (pte_none_or_zero (pteval)) {add_mm_counter (vma->vm_mm,MM_ANONPAGES ,1 ); -if (is_zero_pfn (pte_pfn (pteval))) { -/* -* ptl mostly unnecessary. -*/ -spin_lock (ptl); -ptep_clear (vma->vm_mm, address, _pte); -spin_unlock (ptl); -ksm_might_unmap_zero_page (vma->vm_mm, pteval); - } +if (pte_none (pteval)) +continue ; +/* +* ptl mostly unnecessary. +*/ +spin_lock (ptl); +ptep_clear (vma->vm_mm, address, _pte); +spin_unlock (ptl); +ksm_might_unmap_zero_page (vma->vm_mm, pteval); }else {struct page *src_page =pte_page (pteval);
@@ -812,7 +819,7 @@ static int __collapse_huge_page_copy(pte_t *pte, struct folio *folio,unsigned long src_addr = address + i *PAGE_SIZE ;struct page *src_page; -if (pte_none (pteval) ||is_zero_pfn (pte_pfn (pteval))) { +if (pte_none_or_zero (pteval)) {clear_user_highpage (page, src_addr);continue ; }
@@ -1305,7 +1312,7 @@ static int hpage_collapse_scan_pmd(struct mm_struct *mm, goto out_unmap; } } -if (pte_none (pteval) ||is_zero_pfn (pte_pfn (pteval))) { +if (pte_none_or_zero (pteval)) { ++none_or_zero; if (!userfaultfd_armed(vma) && (!cc->is_khugepaged ||
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 userfaultfd: prevent registration of special VMAs
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.
--- include/linux/userfaultfd_k.h | 6 ++++++ 1 file changed, 6 insertions(+)
include/linux/userfaultfd_k.h +6 -0
@@ -216,6 +216,12 @@ static inline bool vma_can_userfault(struct vm_area_struct *vma, unsigned long vm_flags, bool wp_async) { +if (vma->vm_flags &VM_SHADOW_STACK ) +return false; + +if (!is_vm_hugetlb_page (vma) && (vma->vm_flags &VM_SPECIAL )) +return false; + vm_flags &= __VM_UFFD_FLAGS;if (vm_flags &VM_DROPPABLE )
Signature · 1 line
2.53.0