* [PATCH 1/5] mm: limit pagecache folio refcount when mapping pages
2026-11-05 13:10 [PATCH 0/5] mm: limit pagecache folio refcount David Hildenbrand (Arm)
@ 2026-11-05 13:10 ` David Hildenbrand (Arm)
2026-11-06 9:11 ` Lance Yang
` (2 more replies)
2026-11-05 13:10 ` [PATCH 2/5] mm: limit pagecache folio refcount when splicing into pipes David Hildenbrand (Arm)
` (5 subsequent siblings)
6 siblings, 3 replies; 25+ messages in thread
From: David Hildenbrand (Arm) @ 2026-11-05 13:10 UTC (permalink / raw)
To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Jason Gunthorpe, Kevin Tian,
Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard
Cc: linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu,
David Hildenbrand (Arm),
Chris Mason, stable
With large file folios, overflowing the folio mapcount and refcount
became possible. For anon folios it is currently not really an issue:
each large anon folio can only be mapped once into a process.
That's not really big news, but it's about time that we do something
about it because some modern technology might find ways to abuse it :)
One of the enablers for that was commit ddc58f27f9ee ("mm: drop tail page
refcounting"), however, file thp support was added later.
File folios can be mapped multiple times into the same process, allowing
for processes to hold many references to the same folio.
As a short-term solution, let's introduce two folio refcount limits:
one for ordinary consumers and one for admins. Leave some headroom
before the refcount goes negative, which we really don't want (having
the mapcount go negative is also not expected).
Start reporting SIGBUS if we run into limits. When restoring mappings
from migration entries, instead zap the pte/pmd entry. We allow for
slightly exceeding the limit to keep things simpler.
This is far from ideal, but better than all easy alternatives we can
backport comfortably. For now it fixes the big problem: letting
the refcount (+mapcount) go negative and cause trouble.
This is only a temporary fix, we'll follow up with something better.
While the refcount checks are not required for order 0 folios, let's
just add them for consistency: each folio_add_file_rmap*() and
folio_dup_file_rmap*() needs a prior check.
Also, just document -EHWPOISON for copy_present_ptes() while at it.
Reported-by: Chris Mason <mason@kernel.org>
Fixes: 800d8c63b2e9 ("shmem: add huge pages support")
Fixes: 99cb0dbd47a1 ("mm,thp: add read-only THP support for (non-shmem) FS")
Fixes: 793917d997df ("mm/readahead: Add large folio readahead")
Cc: stable@vger.kernel.org
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
include/linux/mm.h | 33 +++++++++++++++++++++++++++++++++
mm/filemap.c | 6 ++++++
mm/huge_memory.c | 24 ++++++++++++++++++++++--
mm/memory.c | 23 ++++++++++++++++++++---
mm/migrate.c | 11 +++++++++++
mm/userfaultfd.c | 4 ++++
6 files changed, 96 insertions(+), 5 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index a2dd76cc5bbfe..79ae8fc0d6bb4 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -8,6 +8,7 @@
#include <linux/gfp.h>
#include <linux/pgalloc_tag.h>
#include <linux/bug.h>
+#include <linux/capability.h>
#include <linux/list.h>
#include <linux/mmzone.h>
#include <linux/rbtree.h>
@@ -2228,6 +2229,38 @@ vm_fault_t finish_fault(struct vm_fault *vmf);
#define folio_ref_zero_or_close_to_overflow(folio) \
((unsigned int) folio_ref_count(folio) + 127u <= 127u)
+/* Leave separate reserves for administrators and concurrent reference gains. */
+#define FOLIO_REF_COUNT_LIMIT (INT_MAX - (1U << 26))
+#define FOLIO_REF_COUNT_ADMIN_LIMIT (INT_MAX - (1U << 25))
+
+/**
+ * folio_ref_count_over_limit - Check whether to refuse more folio references.
+ * @folio: The folio.
+ *
+ * Relevant for large pagecache folios (!hugetlb). For these, we have to check
+ * before adding page table mappings or other significant refcount users whether
+ * we are close to our folio ref count limit, to avoid overflows.
+ *
+ * Checking this for other folios does no harm but is mostly unnecessary.
+ *
+ * This check is an approximation; we leave some headroom such that concurrent
+ * increments, batches and temporary references are not a problem.
+ *
+ * Return: True if the caller should refuse additional references, false
+ * otherwise.
+ */
+static inline bool folio_ref_count_over_limit(const struct folio *folio)
+{
+ const unsigned int ref_count = folio_ref_count(folio);
+
+ if (likely(ref_count < FOLIO_REF_COUNT_LIMIT))
+ return false;
+ if (ref_count >= FOLIO_REF_COUNT_ADMIN_LIMIT)
+ return true;
+ /* Background threads must not consume admin reserves. */
+ return (current->flags & PF_KTHREAD) || !capable(CAP_SYS_RESOURCE);
+}
+
/**
* folio_get - Increment the reference count on a folio.
* @folio: The folio.
diff --git a/mm/filemap.c b/mm/filemap.c
index 86297841f9955..920bbf86dfdff 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -3968,6 +3968,11 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
unsigned long end;
vm_fault_t map_ret;
+ if (unlikely(folio_ref_count_over_limit(folio))) {
+ folio_ref_dec(folio);
+ goto next;
+ }
+
addr += (xas.xa_index - last_pgoff) << PAGE_SHIFT;
vmf->pte += xas.xa_index - last_pgoff;
last_pgoff = xas.xa_index;
@@ -4009,6 +4014,7 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
mmap_miss - 1);
}
+next:
folio_unlock(folio);
} while ((folio = next_uptodate_folio(&xas, mapping, end_pgoff)) != NULL);
add_mm_counter(vma->vm_mm, folio_type, rss);
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index d0e19d9e6b651..2596ff0f0e185 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1626,6 +1626,7 @@ static vm_fault_t insert_pmd(struct vm_area_struct *vma, unsigned long addr,
{
struct mm_struct *mm = vma->vm_mm;
pgtable_t pgtable = NULL;
+ vm_fault_t ret = VM_FAULT_NOPAGE;
spinlock_t *ptl;
pmd_t entry;
@@ -1662,6 +1663,10 @@ static vm_fault_t insert_pmd(struct vm_area_struct *vma, unsigned long addr,
if (is_huge_zero_folio(fop.folio)) {
entry = pmd_mkspecial(entry);
} else {
+ if (unlikely(folio_ref_count_over_limit(fop.folio))) {
+ ret = VM_FAULT_SIGBUS;
+ goto out_unlock;
+ }
folio_get(fop.folio);
folio_add_file_rmap_pmd(fop.folio, &fop.folio->page, vma);
add_mm_counter(mm, mm_counter_file(fop.folio), HPAGE_PMD_NR);
@@ -1688,7 +1693,7 @@ static vm_fault_t insert_pmd(struct vm_area_struct *vma, unsigned long addr,
spin_unlock(ptl);
if (pgtable)
pte_free(mm, pgtable);
- return VM_FAULT_NOPAGE;
+ return ret;
}
/**
@@ -1759,6 +1764,7 @@ static vm_fault_t insert_pud(struct vm_area_struct *vma, unsigned long addr,
pud_t *pud, struct folio_or_pfn fop, pgprot_t prot, bool write)
{
struct mm_struct *mm = vma->vm_mm;
+ vm_fault_t ret = VM_FAULT_NOPAGE;
spinlock_t *ptl;
pud_t entry;
@@ -1784,6 +1790,10 @@ static vm_fault_t insert_pud(struct vm_area_struct *vma, unsigned long addr,
if (fop.is_folio) {
entry = folio_mk_pud(fop.folio, vma->vm_page_prot);
+ if (unlikely(folio_ref_count_over_limit(fop.folio))) {
+ ret = VM_FAULT_SIGBUS;
+ goto out_unlock;
+ }
folio_get(fop.folio);
folio_add_file_rmap_pud(fop.folio, &fop.folio->page, vma);
add_mm_counter(mm, mm_counter_file(fop.folio), HPAGE_PUD_NR);
@@ -1799,7 +1809,7 @@ static vm_fault_t insert_pud(struct vm_area_struct *vma, unsigned long addr,
update_mmu_cache_pud(vma, addr, pud);
out_unlock:
spin_unlock(ptl);
- return VM_FAULT_NOPAGE;
+ return ret;
}
/**
@@ -5215,6 +5225,16 @@ void remove_migration_pmd(struct page_vma_mapped_walk *pvmw, struct folio *folio
if (!(pvmw->pmd && !pvmw->pte))
return;
+ if (!folio_test_anon(folio) && unlikely(folio_ref_count_over_limit(folio))) {
+ /* Leave the file mapping absent so it can be faulted in. */
+ pmd_clear(pvmw->pmd);
+ if (arch_needs_pgtable_deposit())
+ zap_deposited_table(mm, pvmw->pmd);
+ update_hiwater_rss(mm);
+ add_mm_counter(mm, mm_counter_file(folio), -HPAGE_PMD_NR);
+ return;
+ }
+
entry = softleaf_from_pmd(*pvmw->pmd);
folio_get(folio);
pmde = folio_mk_pmd(folio, READ_ONCE(vma->vm_page_prot));
diff --git a/mm/memory.c b/mm/memory.c
index becf53a2a0944..4800a0da14a32 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1168,6 +1168,8 @@ static __always_inline void __copy_present_ptes(struct vm_area_struct *dst_vma,
* consecutive pages of the same folio by copying them as well.
*
* Returns -EAGAIN if one preallocated page is required to copy the next PTE.
+ * Returns -ENOMEM if the file folio refcount is too high.
+ * Returns -EHWPOISON if copying a page fails.
* Otherwise, returns the number of copied PTEs (at least 1).
*/
static inline int
@@ -1186,6 +1188,9 @@ copy_present_ptes(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma
folio = page_folio(page);
+ if (!folio_test_anon(folio) && unlikely(folio_ref_count_over_limit(folio)))
+ return -ENOMEM;
+
/*
* If we likely have to copy, just don't bother with batching. Make
* sure that the common "small folio" case is as fast as possible
@@ -1367,9 +1372,9 @@ copy_pte_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma,
/*
* If we need a pre-allocated page for this pte, drop the
* locks, allocate, and try again.
- * If copy failed due to hwpoison in source page, break out.
+ * Other errors abort the copy after releasing the page table locks.
*/
- if (unlikely(ret == -EAGAIN || ret == -EHWPOISON))
+ if (unlikely(ret < 0))
break;
if (unlikely(prealloc)) {
/*
@@ -1399,7 +1404,7 @@ copy_pte_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma,
goto out;
}
entry.val = 0;
- } else if (ret == -EBUSY || unlikely(ret == -EHWPOISON)) {
+ } else if (ret == -EBUSY || ret == -ENOMEM || unlikely(ret == -EHWPOISON)) {
goto out;
} else if (ret == -EAGAIN) {
prealloc = folio_prealloc(src_mm, src_vma, addr, false);
@@ -2469,6 +2474,8 @@ static int insert_page_into_pte_locked(struct vm_area_struct *vma, pte_t *pte,
if (unlikely(is_zero_folio(folio))) {
pteval = pte_mkspecial(pteval);
} else {
+ if (unlikely(folio_ref_count_over_limit(folio)))
+ return -EOVERFLOW;
folio_get(folio);
pteval = mk_pte(page, prot);
if (mkwrite) {
@@ -5717,6 +5724,9 @@ vm_fault_t do_set_pmd(struct vm_fault *vmf, struct folio *folio, struct page *pa
if (unlikely(folio_test_has_hwpoisoned(folio)))
return ret;
+ if (unlikely(folio_ref_count_over_limit(folio)))
+ return VM_FAULT_SIGBUS;
+
/*
* Archs like ppc64 need additional space to store information
* related to pte entry. Use the preallocated table for that.
@@ -5771,6 +5781,9 @@ vm_fault_t do_set_pmd(struct vm_fault *vmf, struct folio *folio, struct page *pa
* @page: The first page to create a PTE for.
* @nr: The number of PTEs to create.
* @addr: The first address to create a PTE for.
+ *
+ * For file mappings, the caller must check folio_ref_count_over_limit()
+ * before adding the mapping references and installing PTEs.
*/
void set_pte_range(struct vm_fault *vmf, struct folio *folio,
struct page *page, unsigned int nr, unsigned long addr)
@@ -5937,6 +5950,10 @@ vm_fault_t finish_fault(struct vm_fault *vmf)
goto fallback;
}
+ if (!is_cow && unlikely(folio_ref_count_over_limit(folio))) {
+ ret = VM_FAULT_SIGBUS;
+ goto unlock;
+ }
folio_ref_add(folio, nr_pages - 1);
set_pte_range(vmf, folio, page, nr_pages, addr);
type = is_cow ? MM_ANONPAGES : mm_counter_file(folio);
diff --git a/mm/migrate.c b/mm/migrate.c
index 6a96e3136fb2a..ca7471aa7a76a 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -385,6 +385,17 @@ static bool remove_migration_pte(struct folio *folio,
try_to_map_unused_to_zeropage(&pvmw, folio, old_pte, idx))
continue;
+ if (!folio_test_anon(folio) && !folio_test_hugetlb(folio) &&
+ unlikely(folio_ref_count_over_limit(folio))) {
+ /* File contents remain available for a later fault. */
+ pte_clear(vma->vm_mm, pvmw.address, pvmw.pte);
+ cond_install_uffd_wp_ptes(vma, pvmw.address,
+ pvmw.pte, old_pte, 1);
+ update_hiwater_rss(vma->vm_mm);
+ dec_mm_counter(vma->vm_mm, mm_counter_file(folio));
+ continue;
+ }
+
folio_get(folio);
new = folio_page(folio, idx);
pte = mk_pte(new, READ_ONCE(vma->vm_page_prot));
diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index 169f681f9849b..89853c157fa91 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -373,6 +373,10 @@ static int mfill_atomic_install_pte(pmd_t *dst_pmd,
goto out_unlock;
if (page_in_cache) {
+ if (unlikely(folio_ref_count_over_limit(folio))) {
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
folio_add_file_rmap_pte(folio, page, dst_vma);
} else {
folio_add_new_anon_rmap(folio, dst_vma, dst_addr, RMAP_EXCLUSIVE);
--
2.43.0
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 1/5] mm: limit pagecache folio refcount when mapping pages
2026-11-05 13:10 ` [PATCH 1/5] mm: limit pagecache folio refcount when mapping pages David Hildenbrand (Arm)
@ 2026-11-06 9:11 ` Lance Yang
2026-11-06 9:42 ` Jose A. Perez de Azpillaga
2026-11-06 12:38 ` Kiryl Shutsemau
2 siblings, 0 replies; 25+ messages in thread
From: Lance Yang @ 2026-11-06 9:11 UTC (permalink / raw)
To: david
Cc: akpm, ljs, liam, vbabka, rppt, surenb, mhocko, willy, jack, ziy,
baolin.wang, nico.pache, ryan.roberts, dev.jain, baohua,
lance.yang, usama.arif, kas, matthew.brost, joshua.hahnjy,
byungchul, gourry, ying.huang, apopple, peterx, hannes,
songliubraving, riel, hughd, will, aneesh.kumar, npiggin, peterz,
jgg, kevin.tian, joro, robin.murphy, steven.sistare, jhubbard,
linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu, mason,
stable
On Thu, Nov 05, 2026 at 02:10:10PM +0100, David Hildenbrand (Arm) wrote:
>With large file folios, overflowing the folio mapcount and refcount
>became possible. For anon folios it is currently not really an issue:
>each large anon folio can only be mapped once into a process.
>
>That's not really big news, but it's about time that we do something
>about it because some modern technology might find ways to abuse it :)
>
>One of the enablers for that was commit ddc58f27f9ee ("mm: drop tail page
>refcounting"), however, file thp support was added later.
>
>File folios can be mapped multiple times into the same process, allowing
>for processes to hold many references to the same folio.
>
>As a short-term solution, let's introduce two folio refcount limits:
>one for ordinary consumers and one for admins. Leave some headroom
>before the refcount goes negative, which we really don't want (having
>the mapcount go negative is also not expected).
>
>Start reporting SIGBUS if we run into limits. When restoring mappings
>from migration entries, instead zap the pte/pmd entry. We allow for
>slightly exceeding the limit to keep things simpler.
>
>This is far from ideal, but better than all easy alternatives we can
>backport comfortably. For now it fixes the big problem: letting
>the refcount (+mapcount) go negative and cause trouble.
>
>This is only a temporary fix, we'll follow up with something better.
>
>While the refcount checks are not required for order 0 folios, let's
>just add them for consistency: each folio_add_file_rmap*() and
>folio_dup_file_rmap*() needs a prior check.
>
>Also, just document -EHWPOISON for copy_present_ptes() while at it.
>
>Reported-by: Chris Mason <mason@kernel.org>
>Fixes: 800d8c63b2e9 ("shmem: add huge pages support")
>Fixes: 99cb0dbd47a1 ("mm,thp: add read-only THP support for (non-shmem) FS")
>Fixes: 793917d997df ("mm/readahead: Add large folio readahead")
>Cc: stable@vger.kernel.org
>Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
>---
> include/linux/mm.h | 33 +++++++++++++++++++++++++++++++++
> mm/filemap.c | 6 ++++++
> mm/huge_memory.c | 24 ++++++++++++++++++++++--
> mm/memory.c | 23 ++++++++++++++++++++---
> mm/migrate.c | 11 +++++++++++
> mm/userfaultfd.c | 4 ++++
> 6 files changed, 96 insertions(+), 5 deletions(-)
Nice work! I just went through all folio_add_file_rmap*() and
folio_dup_file_rmap*() callers, including callers of set_pte_range().
All covered, looks good to me1
Reviewed-by: Lance Yang <lance.yang@linux.dev>
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 1/5] mm: limit pagecache folio refcount when mapping pages
2026-11-05 13:10 ` [PATCH 1/5] mm: limit pagecache folio refcount when mapping pages David Hildenbrand (Arm)
2026-11-06 9:11 ` Lance Yang
@ 2026-11-06 9:42 ` Jose A. Perez de Azpillaga
2026-11-06 10:05 ` David Hildenbrand (Arm)
2026-11-06 10:06 ` Lance Yang
2026-11-06 12:38 ` Kiryl Shutsemau
2 siblings, 2 replies; 25+ messages in thread
From: Jose A. Perez de Azpillaga @ 2026-11-06 9:42 UTC (permalink / raw)
To: David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Jason Gunthorpe, Kevin Tian,
Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard
Cc: linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu,
Chris Mason, stable
On 11/5/26 2:10 PM, David Hildenbrand (Arm) wrote:
> With large file folios, overflowing the folio mapcount and refcount
> became possible. For anon folios it is currently not really an issue:
> each large anon folio can only be mapped once into a process.
>
> That's not really big news, but it's about time that we do something
> about it because some modern technology might find ways to abuse it :)
>
> One of the enablers for that was commit ddc58f27f9ee ("mm: drop tail page
> refcounting"), however, file thp support was added later.
>
> File folios can be mapped multiple times into the same process, allowing
> for processes to hold many references to the same folio.
>
> As a short-term solution, let's introduce two folio refcount limits:
> one for ordinary consumers and one for admins. Leave some headroom
> before the refcount goes negative, which we really don't want (having
> the mapcount go negative is also not expected).
>
> Start reporting SIGBUS if we run into limits. When restoring mappings
> from migration entries, instead zap the pte/pmd entry. We allow for
> slightly exceeding the limit to keep things simpler.
>
> This is far from ideal, but better than all easy alternatives we can
> backport comfortably. For now it fixes the big problem: letting
> the refcount (+mapcount) go negative and cause trouble.
>
> This is only a temporary fix, we'll follow up with something better.
>
> While the refcount checks are not required for order 0 folios, let's
> just add them for consistency: each folio_add_file_rmap*() and
> folio_dup_file_rmap*() needs a prior check.
in mm-new copy_huge_pmd() now does a folio_dup_file_rmap_pmd() at fork,
since Konstantin's "mm/huge_memory: copy file THPs at fork like
copy_present_ptes() does". doesn't that one need the check too?
the rest LGTM:
Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com>
--
cheers,
jose a. p-a
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 1/5] mm: limit pagecache folio refcount when mapping pages
2026-11-06 9:42 ` Jose A. Perez de Azpillaga
@ 2026-11-06 10:05 ` David Hildenbrand (Arm)
2026-11-06 10:06 ` Lance Yang
1 sibling, 0 replies; 25+ messages in thread
From: David Hildenbrand (Arm) @ 2026-11-06 10:05 UTC (permalink / raw)
To: Jose A. Perez de Azpillaga, Andrew Morton, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Jason Gunthorpe, Kevin Tian,
Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard
Cc: linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu,
Chris Mason, stable
On 11/6/26 10:42, Jose A. Perez de Azpillaga wrote:
> On 11/5/26 2:10 PM, David Hildenbrand (Arm) wrote:
>> With large file folios, overflowing the folio mapcount and refcount
>> became possible. For anon folios it is currently not really an issue:
>> each large anon folio can only be mapped once into a process.
>>
>> That's not really big news, but it's about time that we do something
>> about it because some modern technology might find ways to abuse it :)
>>
>> One of the enablers for that was commit ddc58f27f9ee ("mm: drop tail page
>> refcounting"), however, file thp support was added later.
>>
>> File folios can be mapped multiple times into the same process, allowing
>> for processes to hold many references to the same folio.
>>
>> As a short-term solution, let's introduce two folio refcount limits:
>> one for ordinary consumers and one for admins. Leave some headroom
>> before the refcount goes negative, which we really don't want (having
>> the mapcount go negative is also not expected).
>>
>> Start reporting SIGBUS if we run into limits. When restoring mappings
>> from migration entries, instead zap the pte/pmd entry. We allow for
>> slightly exceeding the limit to keep things simpler.
>>
>> This is far from ideal, but better than all easy alternatives we can
>> backport comfortably. For now it fixes the big problem: letting
>> the refcount (+mapcount) go negative and cause trouble.
>>
>> This is only a temporary fix, we'll follow up with something better.
>>
>> While the refcount checks are not required for order 0 folios, let's
>> just add them for consistency: each folio_add_file_rmap*() and
>> folio_dup_file_rmap*() needs a prior check.
> in mm-new copy_huge_pmd() now does a folio_dup_file_rmap_pmd() at fork,
> since Konstantin's "mm/huge_memory: copy file THPs at fork like
> copy_present_ptes() does". doesn't that one need the check too?
Yes, that one will need care as well, thanks. I think I missed it when rebasing
on top of the other fixes.
Thanks!
--
Cheers,
David
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 1/5] mm: limit pagecache folio refcount when mapping pages
2026-11-06 9:42 ` Jose A. Perez de Azpillaga
2026-11-06 10:05 ` David Hildenbrand (Arm)
@ 2026-11-06 10:06 ` Lance Yang
1 sibling, 0 replies; 25+ messages in thread
From: Lance Yang @ 2026-11-06 10:06 UTC (permalink / raw)
To: azpijr, david
Cc: akpm, ljs, liam, vbabka, rppt, surenb, mhocko, willy, jack, ziy,
baolin.wang, nico.pache, ryan.roberts, dev.jain, baohua,
lance.yang, usama.arif, kas, matthew.brost, joshua.hahnjy,
byungchul, gourry, ying.huang, apopple, peterx, hannes,
songliubraving, riel, hughd, will, aneesh.kumar, npiggin, peterz,
jgg, kevin.tian, joro, robin.murphy, steven.sistare, jhubbard,
linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu, mason,
stable
On Fri, Nov 06, 2026 at 10:42:17AM +0100, Jose A. Perez de Azpillaga wrote:
>On 11/5/26 2:10 PM, David Hildenbrand (Arm) wrote:
>> With large file folios, overflowing the folio mapcount and refcount
>> became possible. For anon folios it is currently not really an issue:
>> each large anon folio can only be mapped once into a process.
>>
>> That's not really big news, but it's about time that we do something
>> about it because some modern technology might find ways to abuse it :)
>>
>> One of the enablers for that was commit ddc58f27f9ee ("mm: drop tail page
>> refcounting"), however, file thp support was added later.
>>
>> File folios can be mapped multiple times into the same process, allowing
>> for processes to hold many references to the same folio.
>>
>> As a short-term solution, let's introduce two folio refcount limits:
>> one for ordinary consumers and one for admins. Leave some headroom
>> before the refcount goes negative, which we really don't want (having
>> the mapcount go negative is also not expected).
>>
>> Start reporting SIGBUS if we run into limits. When restoring mappings
>> from migration entries, instead zap the pte/pmd entry. We allow for
>> slightly exceeding the limit to keep things simpler.
>>
>> This is far from ideal, but better than all easy alternatives we can
>> backport comfortably. For now it fixes the big problem: letting
>> the refcount (+mapcount) go negative and cause trouble.
>>
>> This is only a temporary fix, we'll follow up with something better.
>>
>> While the refcount checks are not required for order 0 folios, let's
>> just add them for consistency: each folio_add_file_rmap*() and
>> folio_dup_file_rmap*() needs a prior check.
>in mm-new copy_huge_pmd() now does a folio_dup_file_rmap_pmd() at fork,
>since Konstantin's "mm/huge_memory: copy file THPs at fork like
>copy_present_ptes() does". doesn't that one need the check too?
Ah, good catch! My local tree didn't have Konstantin's series [1] yet. And
right, that path needs a check too I guess :)
[1] https://lore.kernel.org/all/20261104-b4-prep-vstor-149847-copy_huge_pmd-recheck-special-pmd-v5-2-c56d0d26f970@virtuozzo.com/
>
>the rest LGTM:
>
>Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com>
>
>--
>cheers,
>jose a. p-a
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 1/5] mm: limit pagecache folio refcount when mapping pages
2026-11-05 13:10 ` [PATCH 1/5] mm: limit pagecache folio refcount when mapping pages David Hildenbrand (Arm)
2026-11-06 9:11 ` Lance Yang
2026-11-06 9:42 ` Jose A. Perez de Azpillaga
@ 2026-11-06 12:38 ` Kiryl Shutsemau
2 siblings, 0 replies; 25+ messages in thread
From: Kiryl Shutsemau @ 2026-11-06 12:38 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Matthew Brost,
Joshua Hahn, Byungchul Park, Gregory Price, Ying Huang,
Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Jason Gunthorpe, Kevin Tian,
Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard, linux-mm,
linux-kernel, linux-fsdevel, linux-arch, iommu, Chris Mason,
stable
On Thu, Nov 05, 2026 at 02:10:10PM +0100, David Hildenbrand (Arm) wrote:
> With large file folios, overflowing the folio mapcount and refcount
> became possible. For anon folios it is currently not really an issue:
> each large anon folio can only be mapped once into a process.
>
> That's not really big news, but it's about time that we do something
> about it because some modern technology might find ways to abuse it :)
>
> One of the enablers for that was commit ddc58f27f9ee ("mm: drop tail page
> refcounting"), however, file thp support was added later.
>
> File folios can be mapped multiple times into the same process, allowing
> for processes to hold many references to the same folio.
>
> As a short-term solution, let's introduce two folio refcount limits:
> one for ordinary consumers and one for admins. Leave some headroom
> before the refcount goes negative, which we really don't want (having
> the mapcount go negative is also not expected).
>
> Start reporting SIGBUS if we run into limits. When restoring mappings
> from migration entries, instead zap the pte/pmd entry. We allow for
> slightly exceeding the limit to keep things simpler.
>
> This is far from ideal, but better than all easy alternatives we can
> backport comfortably. For now it fixes the big problem: letting
> the refcount (+mapcount) go negative and cause trouble.
>
> This is only a temporary fix, we'll follow up with something better.
>
> While the refcount checks are not required for order 0 folios, let's
> just add them for consistency: each folio_add_file_rmap*() and
> folio_dup_file_rmap*() needs a prior check.
>
> Also, just document -EHWPOISON for copy_present_ptes() while at it.
>
> Reported-by: Chris Mason <mason@kernel.org>
> Fixes: 800d8c63b2e9 ("shmem: add huge pages support")
> Fixes: 99cb0dbd47a1 ("mm,thp: add read-only THP support for (non-shmem) FS")
> Fixes: 793917d997df ("mm/readahead: Add large folio readahead")
> Cc: stable@vger.kernel.org
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> ---
> include/linux/mm.h | 33 +++++++++++++++++++++++++++++++++
> mm/filemap.c | 6 ++++++
> mm/huge_memory.c | 24 ++++++++++++++++++++++--
> mm/memory.c | 23 ++++++++++++++++++++---
> mm/migrate.c | 11 +++++++++++
> mm/userfaultfd.c | 4 ++++
> 6 files changed, 96 insertions(+), 5 deletions(-)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index a2dd76cc5bbfe..79ae8fc0d6bb4 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -8,6 +8,7 @@
> #include <linux/gfp.h>
> #include <linux/pgalloc_tag.h>
> #include <linux/bug.h>
> +#include <linux/capability.h>
> #include <linux/list.h>
> #include <linux/mmzone.h>
> #include <linux/rbtree.h>
> @@ -2228,6 +2229,38 @@ vm_fault_t finish_fault(struct vm_fault *vmf);
> #define folio_ref_zero_or_close_to_overflow(folio) \
> ((unsigned int) folio_ref_count(folio) + 127u <= 127u)
>
> +/* Leave separate reserves for administrators and concurrent reference gains. */
> +#define FOLIO_REF_COUNT_LIMIT (INT_MAX - (1U << 26))
> +#define FOLIO_REF_COUNT_ADMIN_LIMIT (INT_MAX - (1U << 25))
> +
> +/**
> + * folio_ref_count_over_limit - Check whether to refuse more folio references.
> + * @folio: The folio.
> + *
> + * Relevant for large pagecache folios (!hugetlb). For these, we have to check
> + * before adding page table mappings or other significant refcount users whether
> + * we are close to our folio ref count limit, to avoid overflows.
> + *
> + * Checking this for other folios does no harm but is mostly unnecessary.
> + *
> + * This check is an approximation; we leave some headroom such that concurrent
> + * increments, batches and temporary references are not a problem.
> + *
> + * Return: True if the caller should refuse additional references, false
> + * otherwise.
> + */
> +static inline bool folio_ref_count_over_limit(const struct folio *folio)
> +{
> + const unsigned int ref_count = folio_ref_count(folio);
> +
> + if (likely(ref_count < FOLIO_REF_COUNT_LIMIT))
> + return false;
> + if (ref_count >= FOLIO_REF_COUNT_ADMIN_LIMIT)
> + return true;
> + /* Background threads must not consume admin reserves. */
> + return (current->flags & PF_KTHREAD) || !capable(CAP_SYS_RESOURCE);
> +}
> +
> /**
> * folio_get - Increment the reference count on a folio.
> * @folio: The folio.
Does the slow path need to be inline at all 15 call sites, GUP-fast
among them?
Maybe only leave the likely() check in inline and move the rest into a
function call?
Something like:
static inline bool folio_ref_count_over_limit(const struct folio *folio)
{
const unsigned int ref_count = folio_ref_count(folio);
if (likely(ref_count < FOLIO_REF_COUNT_LIMIT))
return false;
return __folio_ref_count_over_limit(ref_count);
}
bool __folio_ref_count_over_limit(unsigned int ref_count)
{
if (ref_count >= FOLIO_REF_COUNT_ADMIN_LIMIT)
return true;
/* Background threads must not consume admin reserves */
if (current->flags & PF_KTHREAD)
return true;
return !capable(CAP_SYS_RESOURCE);
}
Also, should this be capable_noaudit()? I am not sure a refused
reference should leave an audit record. cap_vm_enough_memory() checks
the admin reserve with CAP_OPT_NOAUDIT.
--
Kiryl Shutsemau / Kirill A. Shutemov
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 2/5] mm: limit pagecache folio refcount when splicing into pipes
2026-11-05 13:10 [PATCH 0/5] mm: limit pagecache folio refcount David Hildenbrand (Arm)
2026-11-05 13:10 ` [PATCH 1/5] mm: limit pagecache folio refcount when mapping pages David Hildenbrand (Arm)
@ 2026-11-05 13:10 ` David Hildenbrand (Arm)
2026-11-06 9:50 ` Jose A. Perez de Azpillaga
` (2 more replies)
2026-11-05 13:10 ` [PATCH 3/5] mm/mmu_gather: flush pending references early before the folio limit David Hildenbrand (Arm)
` (4 subsequent siblings)
6 siblings, 3 replies; 25+ messages in thread
From: David Hildenbrand (Arm) @ 2026-11-05 13:10 UTC (permalink / raw)
To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Jason Gunthorpe, Kevin Tian,
Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard
Cc: linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu,
David Hildenbrand (Arm),
stable
Similar to mapping pagecache folios into page tables, let's reject splicing
folios into a pipe if the refcount is at it's limit, similar to how we
handle it during GUP.
This will prevent more cases of possible folio refcount overflows with
large pagecache folios.
Let's keep it simple and check in the two callers of
splice_folio_into_pipe().
Also check in try_get_page() to cover pipe-buffer duplication by tee()
and partial pipe-to-pipe splicing.
Fixes: 800d8c63b2e9 ("shmem: add huge pages support")
Fixes: 99cb0dbd47a1 ("mm,thp: add read-only THP support for (non-shmem) FS")
Fixes: 793917d997df ("mm/readahead: Add large folio readahead")
Cc: stable@vger.kernel.org
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
include/linux/mm.h | 9 ++++++---
mm/filemap.c | 4 ++++
mm/shmem.c | 4 ++++
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 79ae8fc0d6bb4..a82cfbce18215 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2287,10 +2287,13 @@ static inline void get_page(struct page *page)
static inline __must_check bool try_get_page(struct page *page)
{
- page = compound_head(page);
- if (WARN_ON_ONCE(page_ref_count(page) <= 0))
+ struct folio *folio = page_folio(page);
+
+ if (WARN_ON_ONCE(folio_ref_count(folio) <= 0))
return false;
- page_ref_inc(page);
+ if (unlikely(folio_ref_count_over_limit(folio)))
+ return false;
+ folio_ref_inc(folio);
return true;
}
diff --git a/mm/filemap.c b/mm/filemap.c
index 920bbf86dfdff..0f2ec790a5b65 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -3168,6 +3168,10 @@ ssize_t filemap_splice_read(struct file *in, loff_t *ppos,
if (writably_mapped)
flush_dcache_folio(folio);
+ if (unlikely(folio_ref_count_over_limit(folio))) {
+ error = -ENOMEM;
+ goto out;
+ }
n = min_t(loff_t, len, isize - *ppos);
n = splice_folio_into_pipe(pipe, folio, *ppos, n);
if (!n)
diff --git a/mm/shmem.c b/mm/shmem.c
index cda1a0f7db99d..1c0f6bceac486 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -3819,6 +3819,10 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
* Ok, we have the page, and it's up-to-date, so we can
* now splice it into the pipe.
*/
+ if (unlikely(folio_ref_count_over_limit(folio))) {
+ error = -ENOMEM;
+ break;
+ }
n = splice_folio_into_pipe(pipe, folio, *ppos, part);
folio_put(folio);
folio = NULL;
--
2.43.0
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 2/5] mm: limit pagecache folio refcount when splicing into pipes
2026-11-05 13:10 ` [PATCH 2/5] mm: limit pagecache folio refcount when splicing into pipes David Hildenbrand (Arm)
@ 2026-11-06 9:50 ` Jose A. Perez de Azpillaga
2026-11-06 10:03 ` Lance Yang
2026-11-06 17:58 ` Josef Bacik
2 siblings, 0 replies; 25+ messages in thread
From: Jose A. Perez de Azpillaga @ 2026-11-06 9:50 UTC (permalink / raw)
To: David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Jason Gunthorpe, Kevin Tian,
Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard
Cc: linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu, stable
On 11/5/26 2:10 PM, David Hildenbrand (Arm) wrote:
> Similar to mapping pagecache folios into page tables, let's reject splicing
> folios into a pipe if the refcount is at it's limit, similar to how we
> handle it during GUP.
>
> This will prevent more cases of possible folio refcount overflows with
> large pagecache folios.
>
> Let's keep it simple and check in the two callers of
> splice_folio_into_pipe().
>
> Also check in try_get_page() to cover pipe-buffer duplication by tee()
> and partial pipe-to-pipe splicing.
>
> Fixes: 800d8c63b2e9 ("shmem: add huge pages support")
> Fixes: 99cb0dbd47a1 ("mm,thp: add read-only THP support for (non-shmem) FS")
> Fixes: 793917d997df ("mm/readahead: Add large folio readahead")
> Cc: stable@vger.kernel.org
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
LGTM:
Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com>
--
cheers,
jose a. p-a
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 2/5] mm: limit pagecache folio refcount when splicing into pipes
2026-11-05 13:10 ` [PATCH 2/5] mm: limit pagecache folio refcount when splicing into pipes David Hildenbrand (Arm)
2026-11-06 9:50 ` Jose A. Perez de Azpillaga
@ 2026-11-06 10:03 ` Lance Yang
2026-11-06 17:58 ` Josef Bacik
2 siblings, 0 replies; 25+ messages in thread
From: Lance Yang @ 2026-11-06 10:03 UTC (permalink / raw)
To: david
Cc: akpm, ljs, liam, vbabka, rppt, surenb, mhocko, willy, jack, ziy,
baolin.wang, nico.pache, ryan.roberts, dev.jain, baohua,
lance.yang, usama.arif, kas, matthew.brost, joshua.hahnjy,
byungchul, gourry, ying.huang, apopple, peterx, hannes,
songliubraving, riel, hughd, will, aneesh.kumar, npiggin, peterz,
jgg, kevin.tian, joro, robin.murphy, steven.sistare, jhubbard,
linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu, stable
On Thu, Nov 05, 2026 at 02:10:11PM +0100, David Hildenbrand (Arm) wrote:
>Similar to mapping pagecache folios into page tables, let's reject splicing
>folios into a pipe if the refcount is at it's limit, similar to how we
>handle it during GUP.
>
>This will prevent more cases of possible folio refcount overflows with
>large pagecache folios.
>
>Let's keep it simple and check in the two callers of
>splice_folio_into_pipe().
>
>Also check in try_get_page() to cover pipe-buffer duplication by tee()
>and partial pipe-to-pipe splicing.
What about fuse_ref_folio()? Buffered FUSE_WRITE requests can carry
pagecache folios into a pipe through /dev/fuse without going through
splice_folio_into_pipe() or try_get_page() ...
Cheers, Lance
>Fixes: 800d8c63b2e9 ("shmem: add huge pages support")
>Fixes: 99cb0dbd47a1 ("mm,thp: add read-only THP support for (non-shmem) FS")
>Fixes: 793917d997df ("mm/readahead: Add large folio readahead")
>Cc: stable@vger.kernel.org
>Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
>---
> include/linux/mm.h | 9 ++++++---
> mm/filemap.c | 4 ++++
> mm/shmem.c | 4 ++++
> 3 files changed, 14 insertions(+), 3 deletions(-)
>
>diff --git a/include/linux/mm.h b/include/linux/mm.h
>index 79ae8fc0d6bb4..a82cfbce18215 100644
>--- a/include/linux/mm.h
>+++ b/include/linux/mm.h
>@@ -2287,10 +2287,13 @@ static inline void get_page(struct page *page)
>
> static inline __must_check bool try_get_page(struct page *page)
> {
>- page = compound_head(page);
>- if (WARN_ON_ONCE(page_ref_count(page) <= 0))
>+ struct folio *folio = page_folio(page);
>+
>+ if (WARN_ON_ONCE(folio_ref_count(folio) <= 0))
> return false;
>- page_ref_inc(page);
>+ if (unlikely(folio_ref_count_over_limit(folio)))
>+ return false;
>+ folio_ref_inc(folio);
> return true;
> }
>
>diff --git a/mm/filemap.c b/mm/filemap.c
>index 920bbf86dfdff..0f2ec790a5b65 100644
>--- a/mm/filemap.c
>+++ b/mm/filemap.c
>@@ -3168,6 +3168,10 @@ ssize_t filemap_splice_read(struct file *in, loff_t *ppos,
> if (writably_mapped)
> flush_dcache_folio(folio);
>
>+ if (unlikely(folio_ref_count_over_limit(folio))) {
>+ error = -ENOMEM;
>+ goto out;
>+ }
> n = min_t(loff_t, len, isize - *ppos);
> n = splice_folio_into_pipe(pipe, folio, *ppos, n);
> if (!n)
>diff --git a/mm/shmem.c b/mm/shmem.c
>index cda1a0f7db99d..1c0f6bceac486 100644
>--- a/mm/shmem.c
>+++ b/mm/shmem.c
>@@ -3819,6 +3819,10 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
> * Ok, we have the page, and it's up-to-date, so we can
> * now splice it into the pipe.
> */
>+ if (unlikely(folio_ref_count_over_limit(folio))) {
>+ error = -ENOMEM;
>+ break;
>+ }
> n = splice_folio_into_pipe(pipe, folio, *ppos, part);
> folio_put(folio);
> folio = NULL;
>
>--
>2.43.0
>
>
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 2/5] mm: limit pagecache folio refcount when splicing into pipes
2026-11-05 13:10 ` [PATCH 2/5] mm: limit pagecache folio refcount when splicing into pipes David Hildenbrand (Arm)
2026-11-06 9:50 ` Jose A. Perez de Azpillaga
2026-11-06 10:03 ` Lance Yang
@ 2026-11-06 17:58 ` Josef Bacik
2026-11-06 20:09 ` David Hildenbrand (Arm)
2 siblings, 1 reply; 25+ messages in thread
From: Josef Bacik @ 2026-11-06 17:58 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Jason Gunthorpe, Kevin Tian,
Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard, linux-mm,
linux-kernel, linux-fsdevel, linux-arch, iommu, stable
On Thu, Nov 05, 2026 at 02:10:11PM +0100, David Hildenbrand (Arm) wrote:
> Similar to mapping pagecache folios into page tables, let's reject splicing
> folios into a pipe if the refcount is at it's limit, similar to how we
> handle it during GUP.
>
> This will prevent more cases of possible folio refcount overflows with
> large pagecache folios.
>
> Let's keep it simple and check in the two callers of
> splice_folio_into_pipe().
>
> Also check in try_get_page() to cover pipe-buffer duplication by tee()
> and partial pipe-to-pipe splicing.
>
> Fixes: 800d8c63b2e9 ("shmem: add huge pages support")
> Fixes: 99cb0dbd47a1 ("mm,thp: add read-only THP support for (non-shmem) FS")
> Fixes: 793917d997df ("mm/readahead: Add large folio readahead")
> Cc: stable@vger.kernel.org
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> ---
> include/linux/mm.h | 9 ++++++---
> mm/filemap.c | 4 ++++
> mm/shmem.c | 4 ++++
> 3 files changed, 14 insertions(+), 3 deletions(-)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 79ae8fc0d6bb4..a82cfbce18215 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -2287,10 +2287,13 @@ static inline void get_page(struct page *page)
>
> static inline __must_check bool try_get_page(struct page *page)
> {
> - page = compound_head(page);
> - if (WARN_ON_ONCE(page_ref_count(page) <= 0))
> + struct folio *folio = page_folio(page);
> +
> + if (WARN_ON_ONCE(folio_ref_count(folio) <= 0))
Since you're here anyway can you change this to something other than
WARN_ON_ONCE, since that results in an OOPS with panic_on_warn set?
Thanks,
Josef
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 2/5] mm: limit pagecache folio refcount when splicing into pipes
2026-11-06 17:58 ` Josef Bacik
@ 2026-11-06 20:09 ` David Hildenbrand (Arm)
2026-11-06 20:43 ` Jason Gunthorpe
0 siblings, 1 reply; 25+ messages in thread
From: David Hildenbrand (Arm) @ 2026-11-06 20:09 UTC (permalink / raw)
To: Josef Bacik
Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Jason Gunthorpe, Kevin Tian,
Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard, linux-mm,
linux-kernel, linux-fsdevel, linux-arch, iommu, stable
On 11/6/26 18:58, Josef Bacik wrote:
> On Thu, Nov 05, 2026 at 02:10:11PM +0100, David Hildenbrand (Arm) wrote:
>> Similar to mapping pagecache folios into page tables, let's reject splicing
>> folios into a pipe if the refcount is at it's limit, similar to how we
>> handle it during GUP.
>>
>> This will prevent more cases of possible folio refcount overflows with
>> large pagecache folios.
>>
>> Let's keep it simple and check in the two callers of
>> splice_folio_into_pipe().
>>
>> Also check in try_get_page() to cover pipe-buffer duplication by tee()
>> and partial pipe-to-pipe splicing.
>>
>> Fixes: 800d8c63b2e9 ("shmem: add huge pages support")
>> Fixes: 99cb0dbd47a1 ("mm,thp: add read-only THP support for (non-shmem) FS")
>> Fixes: 793917d997df ("mm/readahead: Add large folio readahead")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
>> ---
>> include/linux/mm.h | 9 ++++++---
>> mm/filemap.c | 4 ++++
>> mm/shmem.c | 4 ++++
>> 3 files changed, 14 insertions(+), 3 deletions(-)
>>
>> diff --git a/include/linux/mm.h b/include/linux/mm.h
>> index 79ae8fc0d6bb4..a82cfbce18215 100644
>> --- a/include/linux/mm.h
>> +++ b/include/linux/mm.h
>> @@ -2287,10 +2287,13 @@ static inline void get_page(struct page *page)
>>
>> static inline __must_check bool try_get_page(struct page *page)
>> {
>> - page = compound_head(page);
>> - if (WARN_ON_ONCE(page_ref_count(page) <= 0))
>> + struct folio *folio = page_folio(page);
>> +
>> + if (WARN_ON_ONCE(folio_ref_count(folio) <= 0))
>
> Since you're here anyway can you change this to something other than
> WARN_ON_ONCE, since that results in an OOPS with panic_on_warn set?
> Thanks,
If it actually turns negative (or 0) with out changes, we had an overflow and
for sure want to know about it :)
--
Cheers,
David
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 2/5] mm: limit pagecache folio refcount when splicing into pipes
2026-11-06 20:09 ` David Hildenbrand (Arm)
@ 2026-11-06 20:43 ` Jason Gunthorpe
2026-11-06 20:45 ` David Hildenbrand (Arm)
0 siblings, 1 reply; 25+ messages in thread
From: Jason Gunthorpe @ 2026-11-06 20:43 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: Josef Bacik, Andrew Morton, Lorenzo Stoakes, Liam R. Howlett,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Kevin Tian, Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard, linux-mm,
linux-kernel, linux-fsdevel, linux-arch, iommu, stable
On Fri, Nov 06, 2026 at 09:09:10PM +0100, David Hildenbrand (Arm) wrote:
> On 11/6/26 18:58, Josef Bacik wrote:
> > On Thu, Nov 05, 2026 at 02:10:11PM +0100, David Hildenbrand (Arm) wrote:
> >> Similar to mapping pagecache folios into page tables, let's reject splicing
> >> folios into a pipe if the refcount is at it's limit, similar to how we
> >> handle it during GUP.
> >>
> >> This will prevent more cases of possible folio refcount overflows with
> >> large pagecache folios.
> >>
> >> Let's keep it simple and check in the two callers of
> >> splice_folio_into_pipe().
> >>
> >> Also check in try_get_page() to cover pipe-buffer duplication by tee()
> >> and partial pipe-to-pipe splicing.
> >>
> >> Fixes: 800d8c63b2e9 ("shmem: add huge pages support")
> >> Fixes: 99cb0dbd47a1 ("mm,thp: add read-only THP support for (non-shmem) FS")
> >> Fixes: 793917d997df ("mm/readahead: Add large folio readahead")
> >> Cc: stable@vger.kernel.org
> >> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> >> ---
> >> include/linux/mm.h | 9 ++++++---
> >> mm/filemap.c | 4 ++++
> >> mm/shmem.c | 4 ++++
> >> 3 files changed, 14 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/include/linux/mm.h b/include/linux/mm.h
> >> index 79ae8fc0d6bb4..a82cfbce18215 100644
> >> --- a/include/linux/mm.h
> >> +++ b/include/linux/mm.h
> >> @@ -2287,10 +2287,13 @@ static inline void get_page(struct page *page)
> >>
> >> static inline __must_check bool try_get_page(struct page *page)
> >> {
> >> - page = compound_head(page);
> >> - if (WARN_ON_ONCE(page_ref_count(page) <= 0))
> >> + struct folio *folio = page_folio(page);
> >> +
> >> + if (WARN_ON_ONCE(folio_ref_count(folio) <= 0))
> >
> > Since you're here anyway can you change this to something other than
> > WARN_ON_ONCE, since that results in an OOPS with panic_on_warn set?
> > Thanks,
>
> If it actually turns negative (or 0) with out changes, we had an overflow and
> for sure want to know about it :)
Yeah, didn't you get Docs merged to clarify WARN_ON is fine if
userspace can't trigger it?
If you use panic_on_warn you *WANT* your system to stop if it detects
corruption, that's the whole point. Removing corruption detection so
panic doesn't trigger is pure 100% nonsense.
This keeps coming up and it's frustrating to go over again and again.
Jason
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 2/5] mm: limit pagecache folio refcount when splicing into pipes
2026-11-06 20:43 ` Jason Gunthorpe
@ 2026-11-06 20:45 ` David Hildenbrand (Arm)
0 siblings, 0 replies; 25+ messages in thread
From: David Hildenbrand (Arm) @ 2026-11-06 20:45 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Josef Bacik, Andrew Morton, Lorenzo Stoakes, Liam R. Howlett,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Kevin Tian, Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard, linux-mm,
linux-kernel, linux-fsdevel, linux-arch, iommu, stable
On 11/6/26 21:43, Jason Gunthorpe wrote:
> On Fri, Nov 06, 2026 at 09:09:10PM +0100, David Hildenbrand (Arm) wrote:
>> On 11/6/26 18:58, Josef Bacik wrote:
>>>
>>> Since you're here anyway can you change this to something other than
>>> WARN_ON_ONCE, since that results in an OOPS with panic_on_warn set?
>>> Thanks,
>>
>> If it actually turns negative (or 0) with out changes, we had an overflow and
>> for sure want to know about it :)
>
> Yeah, didn't you get Docs merged to clarify WARN_ON is fine if
> userspace can't trigger it?
Yes, I pointed Josef at it off-list.
--
Cheers,
David
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 3/5] mm/mmu_gather: flush pending references early before the folio limit
2026-11-05 13:10 [PATCH 0/5] mm: limit pagecache folio refcount David Hildenbrand (Arm)
2026-11-05 13:10 ` [PATCH 1/5] mm: limit pagecache folio refcount when mapping pages David Hildenbrand (Arm)
2026-11-05 13:10 ` [PATCH 2/5] mm: limit pagecache folio refcount when splicing into pipes David Hildenbrand (Arm)
@ 2026-11-05 13:10 ` David Hildenbrand (Arm)
2026-11-06 9:56 ` Jose A. Perez de Azpillaga
2026-11-06 15:15 ` Lance Yang
2026-11-05 13:10 ` [PATCH 4/5] iommufd: fix cleanup when adding memfd folio pins fails David Hildenbrand (Arm)
` (3 subsequent siblings)
6 siblings, 2 replies; 25+ messages in thread
From: David Hildenbrand (Arm) @ 2026-11-05 13:10 UTC (permalink / raw)
To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Jason Gunthorpe, Kevin Tian,
Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard
Cc: linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu,
David Hildenbrand (Arm),
Chris Mason, stable
When a task zaps mappings (e.g., MADV_DONTNEED), it can drop the PT lock
and defer dropping the folio references. In the meantime, page faults
can refault pagecache folios, creating more references for the same
folios.
Let's just request a flush after enqueueing a pagecache folio whose
refcount reached a certain threshold. Start flushing well before new
references are refused, regardless of the caller's privileges.
This is a temporary measure until we have something better.
Reported-by: Chris Mason <mason@kernel.org>
Fixes: 10ebac4f95e7 ("mm/memory: optimize unmap/zap with PTE-mapped THP")
Cc: stable@vger.kernel.org
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
include/linux/mm.h | 1 +
mm/memory.c | 4 ++--
mm/mmu_gather.c | 5 +++++
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index a82cfbce18215..87f7646a7f3ba 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2232,6 +2232,7 @@ vm_fault_t finish_fault(struct vm_fault *vmf);
/* Leave separate reserves for administrators and concurrent reference gains. */
#define FOLIO_REF_COUNT_LIMIT (INT_MAX - (1U << 26))
#define FOLIO_REF_COUNT_ADMIN_LIMIT (INT_MAX - (1U << 25))
+#define FOLIO_REF_COUNT_FLUSH_LIMIT (INT_MAX - (1U << 27))
/**
* folio_ref_count_over_limit - Check whether to refuse more folio references.
diff --git a/mm/memory.c b/mm/memory.c
index 4800a0da14a32..d2eb313832559 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2061,8 +2061,8 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
pte_unmap_unlock(start_pte, ptl);
/*
- * If we forced a TLB flush (either due to running out of
- * batch buffers or because we needed to flush dirty TLB
+ * If we forced a TLB flush (either to release batched
+ * references or because we needed to flush dirty TLB
* entries before releasing the ptl), free the batched
* memory too. Come back again if we didn't do everything.
*/
diff --git a/mm/mmu_gather.c b/mm/mmu_gather.c
index 9f353f0e2ef4d..5988c42cc5144 100644
--- a/mm/mmu_gather.c
+++ b/mm/mmu_gather.c
@@ -190,6 +190,11 @@ static bool __tlb_remove_folio_pages_size(struct mmu_gather *tlb,
batch->encoded_pages[batch->nr++] = encode_page(page, flags);
batch->encoded_pages[batch->nr++] = encode_nr_pages(nr_pages);
}
+ /* Flush pending references well before new references are refused. */
+ if (unlikely((unsigned int)folio_ref_count(page_folio(page)) >=
+ FOLIO_REF_COUNT_FLUSH_LIMIT))
+ return true;
+
/*
* Make sure that we can always add another "page" + "nr_pages",
* requiring two entries instead of only a single one.
--
2.43.0
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 3/5] mm/mmu_gather: flush pending references early before the folio limit
2026-11-05 13:10 ` [PATCH 3/5] mm/mmu_gather: flush pending references early before the folio limit David Hildenbrand (Arm)
@ 2026-11-06 9:56 ` Jose A. Perez de Azpillaga
2026-11-06 15:15 ` Lance Yang
1 sibling, 0 replies; 25+ messages in thread
From: Jose A. Perez de Azpillaga @ 2026-11-06 9:56 UTC (permalink / raw)
To: David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Jason Gunthorpe, Kevin Tian,
Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard
Cc: linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu,
Chris Mason, stable
On 11/5/26 2:10 PM, David Hildenbrand (Arm) wrote:
> When a task zaps mappings (e.g., MADV_DONTNEED), it can drop the PT lock
> and defer dropping the folio references. In the meantime, page faults
> can refault pagecache folios, creating more references for the same
> folios.
>
> Let's just request a flush after enqueueing a pagecache folio whose
> refcount reached a certain threshold. Start flushing well before new
> references are refused, regardless of the caller's privileges.
>
> This is a temporary measure until we have something better.
>
> Reported-by: Chris Mason <mason@kernel.org>
> Fixes: 10ebac4f95e7 ("mm/memory: optimize unmap/zap with PTE-mapped THP")
> Cc: stable@vger.kernel.org
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
LGTM:
Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com>
--
cheers,
jose a. p-a
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 3/5] mm/mmu_gather: flush pending references early before the folio limit
2026-11-05 13:10 ` [PATCH 3/5] mm/mmu_gather: flush pending references early before the folio limit David Hildenbrand (Arm)
2026-11-06 9:56 ` Jose A. Perez de Azpillaga
@ 2026-11-06 15:15 ` Lance Yang
1 sibling, 0 replies; 25+ messages in thread
From: Lance Yang @ 2026-11-06 15:15 UTC (permalink / raw)
To: david
Cc: akpm, ljs, liam, vbabka, rppt, surenb, mhocko, willy, jack, ziy,
baolin.wang, nico.pache, ryan.roberts, dev.jain, baohua,
lance.yang, usama.arif, kas, matthew.brost, joshua.hahnjy,
byungchul, gourry, ying.huang, apopple, peterx, hannes,
songliubraving, riel, hughd, will, aneesh.kumar, npiggin, peterz,
jgg, kevin.tian, joro, robin.murphy, steven.sistare, jhubbard,
linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu, mason,
stable
On Thu, Nov 05, 2026 at 02:10:12PM +0100, David Hildenbrand (Arm) wrote:
>When a task zaps mappings (e.g., MADV_DONTNEED), it can drop the PT lock
>and defer dropping the folio references. In the meantime, page faults
>can refault pagecache folios, creating more references for the same
>folios.
>
>Let's just request a flush after enqueueing a pagecache folio whose
>refcount reached a certain threshold. Start flushing well before new
>references are refused, regardless of the caller's privileges.
>
>This is a temporary measure until we have something better.
>
>Reported-by: Chris Mason <mason@kernel.org>
>Fixes: 10ebac4f95e7 ("mm/memory: optimize unmap/zap with PTE-mapped THP")
>Cc: stable@vger.kernel.org
>Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
>---
Reviewed-by: Lance Yang <lance.yang@linux.dev>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 4/5] iommufd: fix cleanup when adding memfd folio pins fails
2026-11-05 13:10 [PATCH 0/5] mm: limit pagecache folio refcount David Hildenbrand (Arm)
` (2 preceding siblings ...)
2026-11-05 13:10 ` [PATCH 3/5] mm/mmu_gather: flush pending references early before the folio limit David Hildenbrand (Arm)
@ 2026-11-05 13:10 ` David Hildenbrand (Arm)
2026-11-06 15:39 ` Lance Yang
2026-11-06 20:46 ` Jason Gunthorpe
2026-11-05 13:10 ` [PATCH 5/5] mm/gup: limit pagecache folio refcount when grabbing references David Hildenbrand (Arm)
` (2 subsequent siblings)
6 siblings, 2 replies; 25+ messages in thread
From: David Hildenbrand (Arm) @ 2026-11-05 13:10 UTC (permalink / raw)
To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Jason Gunthorpe, Kevin Tian,
Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard
Cc: linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu,
David Hildenbrand (Arm),
stable
folio_add_pins() can fail after memfd_pin_folios() succeeded pinning a
folio. Upcoming folio refcount limit checks will make this easier to
trigger.
Let's fix three problems in the error handling:
1. pfn_reader_release_pins() uses the allocated array size instead of the
number of folios returned by memfd_pin_folios(). With large folios,
cleanup can unpin uninitialized entries. Remember the number of returned
folios and use that during cleanup.
2. pin_memfd_pages() returns on failure without releasing the pins acquired
by the current call. Release the per-page pins for folios already
expanded into the page array, and the single pins for the remaining
folios.
3. pfn_reader_next() returns on failure before updating batch_end_index,
even if the batch already contains successfully expanded folios. Update
it before propagating the error so cleanup releases those pins as well.
Fixes: 92687c793644 ("iommufd: pfn_reader for file mappings")
Cc: stable@vger.kernel.org
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
drivers/iommu/iommufd/pages.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/iommufd/pages.c b/drivers/iommu/iommufd/pages.c
index 2f6153108add7..fcdbde007a9ab 100644
--- a/drivers/iommu/iommufd/pages.c
+++ b/drivers/iommu/iommufd/pages.c
@@ -781,6 +781,7 @@ struct pfn_reader_user {
struct file *file;
struct folio **ufolios;
size_t ufolios_len;
+ unsigned long ufolios_count;
unsigned long ufolios_offset;
struct folio **ufolios_next;
};
@@ -800,6 +801,7 @@ static void pfn_reader_user_init(struct pfn_reader_user *user,
user->file = (pages->type == IOPT_ADDRESS_FILE) ? pages->file : NULL;
user->ufolios = NULL;
user->ufolios_len = 0;
+ user->ufolios_count = 0;
user->ufolios_next = NULL;
user->ufolios_offset = 0;
}
@@ -843,6 +845,7 @@ static long pin_memfd_pages(struct pfn_reader_user *user, unsigned long start,
offset >>= PAGE_SHIFT;
user->ufolios_next = user->ufolios;
+ user->ufolios_count = nfolios;
user->ufolios_offset = offset;
for (i = 0; i < nfolios; i++) {
@@ -859,8 +862,12 @@ static long pin_memfd_pages(struct pfn_reader_user *user, unsigned long start,
} else {
int rc = folio_add_pins(folio, npin - 1);
- if (rc)
+ if (rc) {
+ unpin_user_pages(user->upages,
+ upages - user->upages);
+ unpin_folios(user->ufolios + i, nfolios - i);
return rc;
+ }
while (npin--)
*upages++ = folio_page(folio, offset++);
@@ -1251,14 +1258,14 @@ static int pfn_reader_next(struct pfn_reader *pfns)
return -EINVAL;
rc = pfn_reader_fill_span(pfns);
+ pfns->batch_end_index = pfns->batch_start_index +
+ pfns->batch.total_pfns;
if (rc)
return rc;
if (WARN_ON(!pfns->batch.total_pfns))
return -EINVAL;
- pfns->batch_end_index =
- pfns->batch_start_index + pfns->batch.total_pfns;
if (pfns->batch_end_index == pfns->span.last_used + 1)
interval_tree_double_span_iter_next(&pfns->span);
@@ -1320,7 +1327,7 @@ static void pfn_reader_release_pins(struct pfn_reader *pfns)
if (!user->file) {
unpin_user_pages(user->upages + start_index, npages);
} else {
- long n = user->ufolios_len / sizeof(*user->ufolios);
+ const unsigned long n = user->ufolios_count;
unpin_folios(user->ufolios_next,
user->ufolios + n - user->ufolios_next);
--
2.43.0
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 4/5] iommufd: fix cleanup when adding memfd folio pins fails
2026-11-05 13:10 ` [PATCH 4/5] iommufd: fix cleanup when adding memfd folio pins fails David Hildenbrand (Arm)
@ 2026-11-06 15:39 ` Lance Yang
2026-11-06 20:46 ` Jason Gunthorpe
1 sibling, 0 replies; 25+ messages in thread
From: Lance Yang @ 2026-11-06 15:39 UTC (permalink / raw)
To: david
Cc: akpm, ljs, liam, vbabka, rppt, surenb, mhocko, willy, jack, ziy,
baolin.wang, nico.pache, ryan.roberts, dev.jain, baohua,
lance.yang, usama.arif, kas, matthew.brost, joshua.hahnjy,
byungchul, gourry, ying.huang, apopple, peterx, hannes,
songliubraving, riel, hughd, will, aneesh.kumar, npiggin, peterz,
jgg, kevin.tian, joro, robin.murphy, steven.sistare, jhubbard,
linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu, stable
On Thu, Nov 05, 2026 at 02:10:13PM +0100, David Hildenbrand (Arm) wrote:
>folio_add_pins() can fail after memfd_pin_folios() succeeded pinning a
>folio. Upcoming folio refcount limit checks will make this easier to
>trigger.
>
>Let's fix three problems in the error handling:
>
>1. pfn_reader_release_pins() uses the allocated array size instead of the
> number of folios returned by memfd_pin_folios(). With large folios,
> cleanup can unpin uninitialized entries. Remember the number of returned
> folios and use that during cleanup.
>
>2. pin_memfd_pages() returns on failure without releasing the pins acquired
> by the current call. Release the per-page pins for folios already
> expanded into the page array, and the single pins for the remaining
> folios.
>
>3. pfn_reader_next() returns on failure before updating batch_end_index,
> even if the batch already contains successfully expanded folios. Update
> it before propagating the error so cleanup releases those pins as well.
>
>Fixes: 92687c793644 ("iommufd: pfn_reader for file mappings")
>Cc: stable@vger.kernel.org
>Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
>---
Nothing jumped out at me, so:
Reviewed-by: Lance Yang <lance.yang@linux.dev>
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 4/5] iommufd: fix cleanup when adding memfd folio pins fails
2026-11-05 13:10 ` [PATCH 4/5] iommufd: fix cleanup when adding memfd folio pins fails David Hildenbrand (Arm)
2026-11-06 15:39 ` Lance Yang
@ 2026-11-06 20:46 ` Jason Gunthorpe
1 sibling, 0 replies; 25+ messages in thread
From: Jason Gunthorpe @ 2026-11-06 20:46 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Kevin Tian, Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard, linux-mm,
linux-kernel, linux-fsdevel, linux-arch, iommu, stable
On Thu, Nov 05, 2026 at 02:10:13PM +0100, David Hildenbrand (Arm) wrote:
> folio_add_pins() can fail after memfd_pin_folios() succeeded pinning a
> folio. Upcoming folio refcount limit checks will make this easier to
> trigger.
>
> Let's fix three problems in the error handling:
>
> 1. pfn_reader_release_pins() uses the allocated array size instead of the
> number of folios returned by memfd_pin_folios(). With large folios,
> cleanup can unpin uninitialized entries. Remember the number of returned
> folios and use that during cleanup.
>
> 2. pin_memfd_pages() returns on failure without releasing the pins acquired
> by the current call. Release the per-page pins for folios already
> expanded into the page array, and the single pins for the remaining
> folios.
>
> 3. pfn_reader_next() returns on failure before updating batch_end_index,
> even if the batch already contains successfully expanded folios. Update
> it before propagating the error so cleanup releases those pins as well.
>
> Fixes: 92687c793644 ("iommufd: pfn_reader for file mappings")
> Cc: stable@vger.kernel.org
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> ---
> drivers/iommu/iommufd/pages.c | 15 +++++++++++----
> 1 file changed, 11 insertions(+), 4 deletions(-)
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Jason
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 5/5] mm/gup: limit pagecache folio refcount when grabbing references
2026-11-05 13:10 [PATCH 0/5] mm: limit pagecache folio refcount David Hildenbrand (Arm)
` (3 preceding siblings ...)
2026-11-05 13:10 ` [PATCH 4/5] iommufd: fix cleanup when adding memfd folio pins fails David Hildenbrand (Arm)
@ 2026-11-05 13:10 ` David Hildenbrand (Arm)
2026-11-06 10:13 ` Jose A. Perez de Azpillaga
2026-11-05 17:51 ` [PATCH 0/5] mm: limit pagecache folio refcount David Hildenbrand (Arm)
2026-11-06 19:49 ` Josef Bacik
6 siblings, 1 reply; 25+ messages in thread
From: David Hildenbrand (Arm) @ 2026-11-05 13:10 UTC (permalink / raw)
To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Jason Gunthorpe, Kevin Tian,
Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard
Cc: linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu,
David Hildenbrand (Arm),
stable
Let's replace our existing safety check by the new
folio_ref_count_over_limit() check in fast and slow GUP before acquiring
additional references or pins.
Keep it simple and use the check for all folio types.
Drop the WARN_ON_ONCE(), because apparently these things can currently
happen with large pagecache folios.
Keep the zero-refcount rejection if the refcount is 0.
Fixes: 800d8c63b2e9 ("shmem: add huge pages support")
Fixes: 99cb0dbd47a1 ("mm,thp: add read-only THP support for (non-shmem) FS")
Fixes: 793917d997df ("mm/readahead: Add large folio readahead")
Cc: stable@vger.kernel.org
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
mm/gup.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/mm/gup.c b/mm/gup.c
index 2ab42fc6834e5..db9db6b2a4662 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -77,7 +77,7 @@ static inline struct folio *try_get_folio(struct page *page, int refs)
retry:
folio = page_folio(page);
- if (WARN_ON_ONCE(folio_ref_count(folio) < 0))
+ if (unlikely(folio_ref_count_over_limit(folio)))
return NULL;
if (unlikely(!folio_ref_try_add(folio, refs)))
return NULL;
@@ -140,7 +140,11 @@ static void gup_put_folio(struct folio *folio, int refs, unsigned int flags)
int __must_check try_grab_folio(struct folio *folio, int refs,
unsigned int flags)
{
- if (WARN_ON_ONCE(folio_ref_count(folio) <= 0))
+ if ((flags & (FOLL_GET | FOLL_PIN)) &&
+ unlikely(folio_ref_count_over_limit(folio)))
+ return -ENOMEM;
+
+ if (WARN_ON_ONCE(!folio_ref_count(folio)))
return -ENOMEM;
if (unlikely(!(flags & FOLL_PCI_P2PDMA) && folio_is_pci_p2pdma(folio)))
@@ -1482,8 +1486,8 @@ static long __get_user_pages(struct mm_struct *mm,
struct folio *folio = page_folio(page);
/*
- * Since we already hold refcount on the
- * large folio, this should never fail.
+ * Grabbing more references can fail once we
+ * hit folio refcount limits.
*/
if (try_grab_folio(folio, page_increm - 1,
gup_flags)) {
--
2.43.0
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 5/5] mm/gup: limit pagecache folio refcount when grabbing references
2026-11-05 13:10 ` [PATCH 5/5] mm/gup: limit pagecache folio refcount when grabbing references David Hildenbrand (Arm)
@ 2026-11-06 10:13 ` Jose A. Perez de Azpillaga
0 siblings, 0 replies; 25+ messages in thread
From: Jose A. Perez de Azpillaga @ 2026-11-06 10:13 UTC (permalink / raw)
To: David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Jason Gunthorpe, Kevin Tian,
Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard
Cc: linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu, stable
On 11/5/26 2:10 PM, David Hildenbrand (Arm) wrote:
> Let's replace our existing safety check by the new
> folio_ref_count_over_limit() check in fast and slow GUP before acquiring
> additional references or pins.
>
> Keep it simple and use the check for all folio types.
>
> Drop the WARN_ON_ONCE(), because apparently these things can currently
> happen with large pagecache folios.
>
> Keep the zero-refcount rejection if the refcount is 0.
>
> Fixes: 800d8c63b2e9 ("shmem: add huge pages support")
> Fixes: 99cb0dbd47a1 ("mm,thp: add read-only THP support for (non-shmem) FS")
> Fixes: 793917d997df ("mm/readahead: Add large folio readahead")
> Cc: stable@vger.kernel.org
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> ---
> mm/gup.c | 12 ++++++++----
> 1 file changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/mm/gup.c b/mm/gup.c
> index 2ab42fc6834e5..db9db6b2a4662 100644
> --- a/mm/gup.c
> +++ b/mm/gup.c
> @@ -77,7 +77,7 @@ static inline struct folio *try_get_folio(struct page *page, int refs)
>
> retry:
> folio = page_folio(page);
> - if (WARN_ON_ONCE(folio_ref_count(folio) < 0))
> + if (unlikely(folio_ref_count_over_limit(folio)))
> return NULL;
> if (unlikely(!folio_ref_try_add(folio, refs)))
> return NULL;
> @@ -140,7 +140,11 @@ static void gup_put_folio(struct folio *folio, int refs, unsigned int flags)
> int __must_check try_grab_folio(struct folio *folio, int refs,
> unsigned int flags)
> {
> - if (WARN_ON_ONCE(folio_ref_count(folio) <= 0))
> + if ((flags & (FOLL_GET | FOLL_PIN)) &&
> + unlikely(folio_ref_count_over_limit(folio)))
> + return -ENOMEM;
> +
> + if (WARN_ON_ONCE(!folio_ref_count(folio)))
> return -ENOMEM;
>
> if (unlikely(!(flags & FOLL_PCI_P2PDMA) && folio_is_pci_p2pdma(folio)))
> @@ -1482,8 +1486,8 @@ static long __get_user_pages(struct mm_struct *mm,
> struct folio *folio = page_folio(page);
>
> /*
> - * Since we already hold refcount on the
> - * large folio, this should never fail.
> + * Grabbing more references can fail once we
> + * hit folio refcount limits.
> */
> if (try_grab_folio(folio, page_increm - 1,
> gup_flags)) {
this can fail now, so shouldn't the error path below return -ENOMEM like
the first page does, instead of -EFAULT?
--
cheers,
jose a. p-a
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 0/5] mm: limit pagecache folio refcount
2026-11-05 13:10 [PATCH 0/5] mm: limit pagecache folio refcount David Hildenbrand (Arm)
` (4 preceding siblings ...)
2026-11-05 13:10 ` [PATCH 5/5] mm/gup: limit pagecache folio refcount when grabbing references David Hildenbrand (Arm)
@ 2026-11-05 17:51 ` David Hildenbrand (Arm)
2026-11-06 19:49 ` Josef Bacik
6 siblings, 0 replies; 25+ messages in thread
From: David Hildenbrand (Arm) @ 2026-11-05 17:51 UTC (permalink / raw)
To: Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Matthew Wilcox (Oracle),
Jan Kara, Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Usama Arif, Kiryl Shutsemau,
Matthew Brost, Joshua Hahn, Byungchul Park, Gregory Price,
Ying Huang, Alistair Popple, Peter Xu, Johannes Weiner, Song Liu,
Rik van Riel, Hugh Dickins, Will Deacon, Aneesh Kumar K.V,
Nick Piggin, Peter Zijlstra, Jason Gunthorpe, Kevin Tian,
Joerg Roedel (AMD),
Robin Murphy, Steve Sistare, John Hubbard
Cc: linux-mm, linux-kernel, linux-fsdevel, linux-arch, iommu,
Chris Mason, stable
On 11/5/26 14:10, David Hildenbrand (Arm) wrote:
> Users can create a lot of folio references to pagecache folios, making
> it possible to overflow the refcount of large folios.
>
> While we knew that one could in theory overflow a folio's refcount, we
> mostly assumed that bad things would happen and it wouldn't go
> unnoticed.
>
> Not so sure if that is really always the case, and leaving that problem
> unsolved is irresponsible, so let's limit pagecache folio refcounts.
>
> This is really only relevant for large folios / thps in the page cache.
> With anon folios (including THPs), we should not be
> able to trigger folio refcount overflows (until we get PUD-sized ones ;) ).
Just a note that I don't think anon THP are as really relevant today, at least
for 4k kernels, as one would usually need that so many processes (consuming so
much memory for everything else) that this is mostly irrelevant in practice as
an attack vector.
At least with 512 pages per THP.
The exception might be arm64 with 16k or 64k page size with 2k. (putting aside
that 512M THPs are barely usable in practice).
#processes to overflow the folio refcount
4k kernel: 512 pages per THP: 4m processes (irrelevant in practice)
16k kernel: 2048 pages per THP: 1m processes (mostly irrelevant in practice)
64k kernel: 8192 pages per THP: 256k processes
The 64k case might be the only relevant one, but I think even there all
processes combined would already consume way more than 100 GiB of kernel memory.
If we really care about the latter case we could throw in some cheap checks
during fork() checks.
Handling migration entry restore / swapin would be a bit more nasty, but not
sure if that's really something to worry about in the big scheme of things.
--
Cheers,
David
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 0/5] mm: limit pagecache folio refcount
2026-11-05 13:10 [PATCH 0/5] mm: limit pagecache folio refcount David Hildenbrand (Arm)
` (5 preceding siblings ...)
2026-11-05 17:51 ` [PATCH 0/5] mm: limit pagecache folio refcount David Hildenbrand (Arm)
@ 2026-11-06 19:49 ` Josef Bacik
2026-11-06 20:31 ` David Hildenbrand (Arm)
6 siblings, 1 reply; 25+ messages in thread
From: Josef Bacik @ 2026-11-06 19:49 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: Andrew Morton, Chris Mason, Lance Yang,
Jose A. Perez de Azpillaga, Kiryl Shutsemau, Jason Gunthorpe,
linux-mm, linux-fsdevel, linux-kernel, iommu
On Thu, Nov 05, 2026 at 02:10:09PM +0100, David Hildenbrand (Arm) wrote:
> Users can create a lot of folio references to pagecache folios, making
> it possible to overflow the refcount of large folios.
This is a summary of my Claude review of everything, minus what has
already been said on the thread. The numbers are from a TCG guest with
the limits lowered to user 6000 and admin 9000.
1) Small folios, 1/5 and 5/5
On an order-0 folio one FOLL_PIN is worth GUP_PIN_COUNTING_BIAS
references, so about 2M pins reach the limit. That used to make GUP
refuse more pins, now it is also SIGBUS on new faults and failing fork
and splice for everybody else. 6 io_uring registered buffers on one
order-0 shmem page (ref 6146) and another task gets SIGBUS mapping it.
Mappings alone can't get a small folio near the limit, so could the
mapping and splice sites skip small folios?
2) Migration, 1/5
remove_migration_pte() and remove_migration_pmd() check the limit for
whoever migrates, not for the owner of the mapping, and kcompactd always
gets the user limit. With mappings in the admin reserve the next
migration drops whatever is over the user limit, in rmap walk order.
At ref 7681, move_pages(MPOL_MF_MOVE_ALL) without CAP_SYS_RESOURCE left
1682 of 7168 PTEs unrestored, including all 512 of an mlock()ed VMA, and
touching them again got SIGBUS for all 1682. Could the restore check
against the admin limit only?
3) fork, 1/5
If the VMA is only copied because it has an anon rmap, the pagecache
PTEs could be left out to refault in the child, like copy_huge_pmd()
does, instead of failing the fork. Only the VM_COPY_ON_FORK cases need
the error.
4) splice, 2/5
filemap_splice_read() fails where read() still works. sendfile(), the
copy_file_range() fallback and overlayfs copy-up get -ENOMEM, and nfsd
turns it into nfserr_jukebox so the client retries for as long as the
folio stays at the limit. Could do_splice_read() fall back to
copy_splice_read(), like it does for O_DIRECT and DAX?
backing_file_splice_read() runs capable() under ctx->cred. overlayfs
lowers CAP_SYS_RESOURCE there, so root never gets the reserve, and fuse
passthrough uses the server's cred, so an unprivileged reader may.
5) Errors
The one condition comes out as SIGBUS, -ENOMEM, -EFAULT (tee, pipe to
pipe, MADV_POPULATE_READ, process_vm_readv), -EIO (/proc/pid/mem),
-EOVERFLOW (vm_insert_page) and -EINVAL (memfd_pin_folios,
fuse_dev_splice_write). Nothing is logged or counted, so there is
nothing that points at the folio.
6) khugepaged, 1/5
try_collapse_pte_mapped_thp() clears the PTEs and drops their
references, and then do_set_pmd() can refuse, so the mapping is gone
although the collapse would have lowered the refcount.
7) Changelogs, comments, stable
- 3/5 doesn't say what goes wrong without it. It is tagged for
10ebac4f95e7 (v6.9) while 1, 2 and 5 go back to v4.8, so 6.6 and older
get the limits without the flush, and it doesn't say why that is fine.
- 3/5 leaves the "queue is (now) full" comments in asm-generic/tlb.h and
above __tlb_remove_folio_pages_size() stale.
- The ufolios_count fix in 4/5 doesn't depend on the rest of the series,
so it could be its own patch for stable.
- 5/5 needs 1/5 and 4/5, which isn't stated for stable.
- After 5/5 the check is the only guard for pins on small folios, the
kernel-doc calls it "mostly unnecessary" for them. The comment in
folio_maybe_dma_pinned() still describes the negative refcount scheme.
Thanks,
Josef
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 0/5] mm: limit pagecache folio refcount
2026-11-06 19:49 ` Josef Bacik
@ 2026-11-06 20:31 ` David Hildenbrand (Arm)
0 siblings, 0 replies; 25+ messages in thread
From: David Hildenbrand (Arm) @ 2026-11-06 20:31 UTC (permalink / raw)
To: Josef Bacik
Cc: Andrew Morton, Chris Mason, Lance Yang,
Jose A. Perez de Azpillaga, Kiryl Shutsemau, Jason Gunthorpe,
linux-mm, linux-fsdevel, linux-kernel, iommu
On 11/6/26 20:49, Josef Bacik wrote:
> On Thu, Nov 05, 2026 at 02:10:09PM +0100, David Hildenbrand (Arm) wrote:
>> Users can create a lot of folio references to pagecache folios, making
>> it possible to overflow the refcount of large folios.
>
> This is a summary of my Claude review of everything, minus what has
> already been said on the thread. The numbers are from a TCG guest with
> the limits lowered to user 6000 and admin 9000.
Thanks.
>
> 1) Small folios, 1/5 and 5/5
>
> On an order-0 folio one FOLL_PIN is worth GUP_PIN_COUNTING_BIAS
> references, so about 2M pins reach the limit. That used to make GUP
> refuse more pins, now it is also SIGBUS on new faults and failing fork
> and splice for everybody else. 6 io_uring registered buffers on one
> order-0 shmem page (ref 6146) and another task gets SIGBUS mapping it.
> Mappings alone can't get a small folio near the limit, so could the
> mapping and splice sites skip small folios?
Sure, our limit slightly lower, but not as much as we would care for small
folios? I assume your LLM is confused about the actual limits vs. your fake limits?
>
> 2) Migration, 1/5
>
> remove_migration_pte() and remove_migration_pmd() check the limit for
> whoever migrates, not for the owner of the mapping, and kcompactd always
> gets the user limit. With mappings in the admin reserve the next
> migration drops whatever is over the user limit, in rmap walk order.
Right.
>
> At ref 7681, move_pages(MPOL_MF_MOVE_ALL) without CAP_SYS_RESOURCE left
> 1682 of 7168 PTEs unrestored, including all 512 of an mlock()ed VMA, and
> touching them again got SIGBUS for all 1682. Could the restore check
> against the admin limit only?
An actual admin access would, however, not SIGBUS. Sure, we harm mlock() as well
but that's just expected.
I don't see why the extra complexity for this temporary solution would be warranted.
>
> 3) fork, 1/5
>
> If the VMA is only copied because it has an anon rmap, the pagecache
> PTEs could be left out to refault in the child, like copy_huge_pmd()
> does, instead of failing the fork. Only the VM_COPY_ON_FORK cases need
> the error.
That could be done indeed, although I am not sure if really relevant in practice.
I'll see if it can easily be done.
>
> 4) splice, 2/5
>
> filemap_splice_read() fails where read() still works. sendfile(), the
> copy_file_range() fallback and overlayfs copy-up get -ENOMEM, and nfsd
> turns it into nfserr_jukebox so the client retries for as long as the
> folio stays at the limit. Could do_splice_read() fall back to
> copy_splice_read(), like it does for O_DIRECT and DAX?
Same as the above. This solution here is not going to be the solution we'll have
upstream soon, so I try to keep it as small as possible.
I'll see if it can easily be done.
>
> backing_file_splice_read() runs capable() under ctx->cred. overlayfs
> lowers CAP_SYS_RESOURCE there, so root never gets the reserve, and fuse
> passthrough uses the server's cred, so an unprivileged reader may.
>
> 5) Errors
>
> The one condition comes out as SIGBUS, -ENOMEM, -EFAULT (tee, pipe to
> pipe, MADV_POPULATE_READ, process_vm_readv), -EIO (/proc/pid/mem),
> -EOVERFLOW (vm_insert_page) and -EINVAL (memfd_pin_folios,
> fuse_dev_splice_write). Nothing is logged or counted, so there is
> nothing that points at the folio.
Right, again, a temporary solution which we can reasonably backport to stable.
>
> 6) khugepaged, 1/5
>
> try_collapse_pte_mapped_thp() clears the PTEs and drops their
> references, and then do_set_pmd() can refuse, so the mapping is gone
> although the collapse would have lowered the refcount.
Am I wrong or #nobodycares?
>
> 7) Changelogs, comments, stable
>
> - 3/5 doesn't say what goes wrong without it. It is tagged for
> 10ebac4f95e7 (v6.9) while 1, 2 and 5 go back to v4.8, so 6.6 and older
> get the limits without the flush, and it doesn't say why that is fine.
Yeah, probably it should go further back. The PTE batching case was just one
scenario. It was possible when batching over VMAs before (which my commit
handles properly).
> - 3/5 leaves the "queue is (now) full" comments in asm-generic/tlb.h and
> above __tlb_remove_folio_pages_size() stale.
That seems easy to fix.
> - The ufolios_count fix in 4/5 doesn't depend on the rest of the series,
> so it could be its own patch for stable.
5/5 makes it easier to trigger. Which is how it was found in the first place.
> - 5/5 needs 1/5 and 4/5, which isn't stated for stable.
lol, they have the same Fixes tags, that sure is good enough in one series.
> - After 5/5 the check is the only guard for pins on small folios, the
> kernel-doc calls it "mostly unnecessary" for them. The comment in
> folio_maybe_dma_pinned() still describes the negative refcount scheme.
Yeah, I'm trying not to change to much becuase the while thing will get ripped
out soon again.
--
Cheers,
David
^ permalink raw reply [flat|nested] 25+ messages in thread