Generic Linux architectural discussions
 help / color / mirror / Atom feed
From: "David Hildenbrand (Arm)" <david@kernel.org>
To: Lorenzo Stoakes <ljs@kernel.org>,
	"Liam R. Howlett" <liam@infradead.org>,
	Vlastimil Babka <vbabka@kernel.org>,
	Mike Rapoport <rppt@kernel.org>,
	Suren Baghdasaryan <surenb@google.com>,
	Michal Hocko <mhocko@suse.com>,
	"Matthew Wilcox (Oracle)" <willy@infradead.org>,
	Jan Kara <jack@suse.cz>,
	Andrew Morton <akpm@linux-foundation.org>,
	Zi Yan <ziy@nvidia.com>,
	Baolin Wang <baolin.wang@linux.alibaba.com>,
	Nico Pache <nico.pache@linux.dev>,
	Ryan Roberts <ryan.roberts@arm.com>, Dev Jain <dev.jain@arm.com>,
	Barry Song <baohua@kernel.org>, Lance Yang <lance.yang@linux.dev>,
	Usama Arif <usama.arif@linux.dev>,
	Kiryl Shutsemau <kas@kernel.org>,
	Matthew Brost <matthew.brost@intel.com>,
	Joshua Hahn <joshua.hahnjy@gmail.com>,
	Byungchul Park <byungchul@sk.com>,
	Gregory Price <gourry@gourry.net>,
	Ying Huang <ying.huang@linux.alibaba.com>,
	Alistair Popple <apopple@nvidia.com>,
	Peter Xu <peterx@redhat.com>,
	Johannes Weiner <hannes@cmpxchg.org>,
	Song Liu <songliubraving@fb.com>, Rik van Riel <riel@surriel.com>,
	Miklos Szeredi <miklos@szeredi.hu>,
	Alexander Viro <viro@zeniv.linux.org.uk>,
	Christian Brauner <brauner@kernel.org>,
	Hugh Dickins <hughd@google.com>, Will Deacon <will@kernel.org>,
	"Aneesh Kumar K.V" <aneesh.kumar@kernel.org>,
	Nick Piggin <npiggin@gmail.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Arnd Bergmann <arnd@arndb.de>, Jason Gunthorpe <jgg@ziepe.ca>,
	Kevin Tian <kevin.tian@intel.com>,
	"Joerg Roedel (AMD)" <joro@8bytes.org>,
	Robin Murphy <robin.murphy@arm.com>,
	Steve Sistare <steven.sistare@oracle.com>,
	John Hubbard <jhubbard@nvidia.com>,
	"Jose A. Perez de Azpillaga" <azpijr@gmail.com>,
	Josef Bacik <josef@toxicpanda.com>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@kernel.org>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Simon Horman <horms@kernel.org>,
	Neal Cardwell <ncardwell@google.com>,
	Kuniyuki Iwashima <kuniyu@google.com>
Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	linux-fsdevel@vger.kernel.org, fuse-devel@lists.linux.dev,
	linux-arch@vger.kernel.org, iommu@lists.linux.dev,
	netdev@vger.kernel.org, Chris Mason <mason@kernel.org>,
	stable@vger.kernel.org, Pedro Falcato <pfalcato@suse.de>
Subject: Re: [PATCH v4 1/9] mm: limit pagecache folio refcount when mapping pages
Date: Sat, 14 Nov 2026 16:29:53 +0100	[thread overview]
Message-ID: <2e6b3b24-a901-4147-a01b-a8da0e7c5ebb@kernel.org> (raw)
In-Reply-To: <20261112-refcount_overflow_stable-v4-1-ad3deef0bd23@kernel.org>

On 11/12/26 23:53, David Hildenbrand (Arm) wrote:
> With large file folios, overflowing the folio mapcount and refcount
> became possible more easily. For anon folios it is currently not really
> an issue: each large anon folio can only be mapped once into a process; on
> 4k kernels it would be more processes than usually allowed on a system,
> and on 16k or 64k kernels the processes alone would consume hundreds of
> GiB. Something to be sorted out at some point, but it's not as urgent.
> 
> Being able to overflow the refcount is 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 and a ratelimited warning 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.
> 
> During fork(), prefer not copying page table entries over failing fork.
> For fault-around, check in next_uptodate_folio() before trying to lock
> the folio.
> 
> Export folio_ref_count_over_limit_slowpath() using EXPORT_SYMBOL_GPL
> right away so modules can use it through try_get_page(), where we will
> use it next.
> 
> Use has_capability_noaudit(current, CAP_SYS_RESOURCE),
> so filesystem credential overrides do not affect access to the admin
> reserve, and to not generate auditing messages simply because we access
> optional reserves.
> 
> Don't grant access to the admin reserve from kernel threads, from
> interrupt context, where "current" is just the interrupted task, or with
> IRQs disabled, as even unaudited capability checks can take locks.
> 
> 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. Keep the mapping checks explicit and
> separate from reference acquisition: most are expected to disappear when
> we rework the underlying refcounting.
> 
> Check order 0 folios as well for consistency: each
> folio_add_file_rmap*() and folio_dup_file_rmap*() needs a prior check.
> 
> Adjust the check in folio_get() to just check for invalid refcounts and
> drop folio_ref_zero_or_close_to_overflow(): we really don't want
> negative refcounts or negative mapcounts. Convert to VM_WARN_ON_FOLIO as
> we touch it.
> 
> Also, just document -EHWPOISON for copy_present_ptes() while at it.
> 
> Note: When zapping file migration entries, uffd-wp is preserved using PTE
> markers, but uffd-rwp protection is lost because there is no corresponding
> marker. try_to_unmap() already has the same problem when unmapping file
> folios, so we'll happily ignore 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
> Reviewed-by: Jose A. Perez de Azpillaga <azpijr@gmail.com>
> Acked-by: Zi Yan <ziy@nvidia.com>
> Reviewed-by: Pedro Falcato <pfalcato@suse.de>
> Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
> ---

I'll squash the following into the applied patch.

I will not print the PFN for now; it's something that can be
forced by a user so exposing the PFN makes me a bit uneasy. If we
are ever sure that exposing the PFN is ok we can easily add it.

As I replied, for these stable fixes I will leave the refcount
handling as it is right now. We don't expect negative refcounts 
r mapcount (folio_mapped() is a prime example). I especially don't
want that in stable kernels where we might have older code that
dependes on that.

That part will be reworked and optimized as I'll change the refcount
handling for page table mappings; then we'll be able to drop the
admin reserve and the limits, and just cap+warn once the refcount goes
negative.

From 423c4226789587ee4aa3e0e34760dab9a52e2947 Mon Sep 17 00:00:00 2001
From: "David Hildenbrand (Arm)" <david@kernel.org>
Date: Sat, 14 Nov 2026 16:27:17 +0100
Subject: [PATCH] fixup

Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
 mm/folio.c | 26 ++++++++++++++++++++++++++
 mm/util.c  | 26 --------------------------
 2 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/mm/folio.c b/mm/folio.c
index dc2c796a4ea74..1cafa45a6a834 100644
--- a/mm/folio.c
+++ b/mm/folio.c
@@ -151,6 +151,32 @@ void __folio_put(struct folio *folio)
 }
 EXPORT_SYMBOL(__folio_put);
 
+bool folio_ref_count_over_limit_slowpath(const struct folio *folio,
+		unsigned int ref_count)
+{
+	if (ref_count >= FOLIO_REF_COUNT_ADMIN_LIMIT)
+		goto over_limit;
+	/* Background threads must not consume admin reserves. */
+	if (current->flags & PF_KTHREAD)
+		goto over_limit;
+	/* Neither must interrupt contexts on behalf of the interrupted task. */
+	if (!in_task())
+		goto over_limit;
+	/* Capability checks are not safe with IRQs disabled. */
+	if (irqs_disabled())
+		goto over_limit;
+	/* Use the task's credentials, which filesystem overrides cannot change. */
+	if (has_capability_noaudit(current, CAP_SYS_RESOURCE))
+		return false;
+
+over_limit:
+	pr_warn_ratelimited("folio:%p refcount:%d mapcount:%d mapping:%p index:%#lx reached refcount limit\n",
+			    folio, (int)ref_count, folio_mapcount(folio),
+			    folio_mapping(folio), folio->index);
+	return true;
+}
+EXPORT_SYMBOL_GPL(folio_ref_count_over_limit_slowpath);
+
 typedef void (*move_fn_t)(struct lruvec *lruvec, struct folio *folio);
 
 /*
diff --git a/mm/util.c b/mm/util.c
index c9c3dc4b490fa..80f6c714844f2 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -791,32 +791,6 @@ int folio_mc_copy(struct folio *dst, struct folio *src)
 }
 EXPORT_SYMBOL(folio_mc_copy);
 
-bool folio_ref_count_over_limit_slowpath(const struct folio *folio,
-		unsigned int ref_count)
-{
-	if (ref_count >= FOLIO_REF_COUNT_ADMIN_LIMIT)
-		goto over_limit;
-	/* Background threads must not consume admin reserves. */
-	if (current->flags & PF_KTHREAD)
-		goto over_limit;
-	/* Neither must interrupt contexts on behalf of the interrupted task. */
-	if (!in_task())
-		goto over_limit;
-	/* Capability checks are not safe with IRQs disabled. */
-	if (irqs_disabled())
-		goto over_limit;
-	/* Use the task's credentials, which filesystem overrides cannot change. */
-	if (has_capability_noaudit(current, CAP_SYS_RESOURCE))
-		return false;
-
-over_limit:
-	pr_warn_ratelimited("folio:%p refcount:%d mapcount:%d mapping:%p reached refcount limit\n",
-			    folio, (int)ref_count, folio_mapcount(folio),
-			    folio_mapping(folio));
-	return true;
-}
-EXPORT_SYMBOL_GPL(folio_ref_count_over_limit_slowpath);
-
 int sysctl_overcommit_memory __read_mostly = OVERCOMMIT_GUESS;
 static int sysctl_overcommit_ratio __read_mostly = 50;
 static unsigned long sysctl_overcommit_kbytes __read_mostly;
-- 
2.56.0


-- 
Cheers,

David

  parent reply	other threads:[~2026-11-14 15:30 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-12 22:53 [PATCH v4 0/9] mm: limit pagecache folio refcount David Hildenbrand (Arm)
2026-11-12 22:53 ` [PATCH v4 1/9] mm: limit pagecache folio refcount when mapping pages David Hildenbrand (Arm)
2026-11-13 19:45   ` Matthew Wilcox
2026-11-13 20:00     ` David Hildenbrand (Arm)
2026-11-14 15:29   ` David Hildenbrand (Arm) [this message]
2026-11-12 22:53 ` [PATCH v4 2/9] mm: limit pagecache folio refcount when splicing into pipes David Hildenbrand (Arm)
2026-11-12 22:53 ` [PATCH v4 3/9] mm/mmu_gather: flush pending references early before the folio limit David Hildenbrand (Arm)
2026-11-12 22:53 ` [PATCH v4 4/9] iommufd: fix cleanup when adding memfd folio pins fails David Hildenbrand (Arm)
2026-11-12 22:53 ` [PATCH v4 5/9] mm/gup: limit pagecache folio refcount when grabbing references David Hildenbrand (Arm)
2026-11-12 22:53 ` [PATCH v4 6/9] net: limit folio refcount when copying skb frag references David Hildenbrand (Arm)
2026-11-12 22:53 ` [PATCH v4 7/9] net: limit folio refcount when rearranging skb frags David Hildenbrand (Arm)
2026-11-12 22:53 ` [PATCH v4 8/9] net: limit folio refcount when splicing pages into skbs David Hildenbrand (Arm)
2026-11-12 22:53 ` [PATCH v4 9/9] net: limit folio refcount when splicing from sockets David Hildenbrand (Arm)
2026-11-13 10:52 ` (subset) [PATCH v4 0/9] mm: limit pagecache folio refcount David Hildenbrand (Arm)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2e6b3b24-a901-4147-a01b-a8da0e7c5ebb@kernel.org \
    --to=david@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=aneesh.kumar@kernel.org \
    --cc=apopple@nvidia.com \
    --cc=arnd@arndb.de \
    --cc=azpijr@gmail.com \
    --cc=baohua@kernel.org \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=brauner@kernel.org \
    --cc=byungchul@sk.com \
    --cc=davem@davemloft.net \
    --cc=dev.jain@arm.com \
    --cc=edumazet@kernel.org \
    --cc=fuse-devel@lists.linux.dev \
    --cc=gourry@gourry.net \
    --cc=hannes@cmpxchg.org \
    --cc=horms@kernel.org \
    --cc=hughd@google.com \
    --cc=iommu@lists.linux.dev \
    --cc=jack@suse.cz \
    --cc=jgg@ziepe.ca \
    --cc=jhubbard@nvidia.com \
    --cc=joro@8bytes.org \
    --cc=josef@toxicpanda.com \
    --cc=joshua.hahnjy@gmail.com \
    --cc=kas@kernel.org \
    --cc=kevin.tian@intel.com \
    --cc=kuba@kernel.org \
    --cc=kuniyu@google.com \
    --cc=lance.yang@linux.dev \
    --cc=liam@infradead.org \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=mason@kernel.org \
    --cc=matthew.brost@intel.com \
    --cc=mhocko@suse.com \
    --cc=miklos@szeredi.hu \
    --cc=ncardwell@google.com \
    --cc=netdev@vger.kernel.org \
    --cc=nico.pache@linux.dev \
    --cc=npiggin@gmail.com \
    --cc=pabeni@redhat.com \
    --cc=peterx@redhat.com \
    --cc=peterz@infradead.org \
    --cc=pfalcato@suse.de \
    --cc=riel@surriel.com \
    --cc=robin.murphy@arm.com \
    --cc=rppt@kernel.org \
    --cc=ryan.roberts@arm.com \
    --cc=songliubraving@fb.com \
    --cc=stable@vger.kernel.org \
    --cc=steven.sistare@oracle.com \
    --cc=surenb@google.com \
    --cc=usama.arif@linux.dev \
    --cc=vbabka@kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    --cc=will@kernel.org \
    --cc=willy@infradead.org \
    --cc=ying.huang@linux.alibaba.com \
    --cc=ziy@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox