From: "David Hildenbrand (Arm)" <david@kernel.org>
To: sashiko-reviews@lists.linux.dev,
Andrew Morton <akpm@linux-foundation.org>,
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>, 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>,
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>,
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>
Cc: linux-mm@kvack.org
Subject: Re: [PATCH 5/5] mm/gup: limit pagecache folio refcount when grabbing references
Date: Fri, 6 Nov 2026 23:50:55 +0100 [thread overview]
Message-ID: <d4559f3c-dc6b-41c3-92ac-8ae0d07ccfcb@kernel.org> (raw)
In-Reply-To: <sashiko-outbox-201446@kernel.org>
On 11/6/26 14:11, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential
> issue to consider:
> - [High] mm/gup: try_get_folio() calls capable() with IRQs disabled in
> GUP-fast
> --
>
> commit 9290efad216cdf3b5ee1cdfafab0a5d9928a1976
> Author: David Hildenbrand (Arm) <david@kernel.org>
>
> mm/gup: limit pagecache folio refcount when grabbing references
>
> This commit replaces the negative refcount safety checks in try_get_folio()
> and try_grab_folio() with folio_ref_count_over_limit() to enforce folio
> refcount limits in fast and slow GUP before acquiring references or pins.
>
>> 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;
>
> [Severity: High]
> Is it safe for try_get_folio() to call folio_ref_count_over_limit() in the
> fast GUP path?
>
> In mm/gup.c, gup_fast() disables hardware interrupts across the page table
> walk:
>
> mm/gup.c:gup_fast() {
> ...
> local_irq_save(flags);
> nr_pinned = gup_fast_pgd_range(start, end, gup_flags, pages);
> local_irq_restore(flags);
> ...
> }
>
> which calls into try_grab_folio_fast() -> try_get_folio() with IRQs
> disabled:
>
> mm/gup.c:try_grab_folio_fast() {
> ...
> /* Raise warn if it is not called in fast GUP */
> VM_WARN_ON_ONCE(!irqs_disabled());
> ...
> }
>
> Furthermore, get_user_page_fast_only() -> gup_fast() -> try_get_folio() is
> invoked from hardirq and NMI contexts, such as perf_prepare_sample() ->
> perf_virt_to_phys() in kernel/events/core.c.
>
> When folio_ref_count(folio) is between FOLIO_REF_COUNT_LIMIT and
> FOLIO_REF_COUNT_ADMIN_LIMIT and current is not a kernel thread,
> folio_ref_count_over_limit() in include/linux/mm.h calls
> capable(CAP_SYS_RESOURCE):
>
> include/linux/mm.h:folio_ref_count_over_limit() {
> 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);
> }
>
> Calling capable(CAP_SYS_RESOURCE) -> ns_capable_common() ->
> security_capable() in these contexts appears to cause several issues:
>
> 1. LSM capability hooks (such as selinux_capable() and apparmor_capable())
> perform audit logging via common_lsm_audit(), which allocates memory and
> acquires spinlock_t, rwlock_t, and SLUB local_lock_t locks. On
> CONFIG_PREEMPT_RT, these are sleeping rt_mutex locks, so acquiring them
> with hardware interrupts disabled in gup_fast() will sleep in an invalid
> atomic context.
>
> 2. When get_user_page_fast_only() is called from hardirq or NMI context,
> acquiring non-IRQ/NMI-safe locks in the LSM, audit, or SLUB paths can
> self-deadlock if the interrupted context on the same CPU already holds
> one of those locks.
>
> 3. In security/apparmor/capability.c, audit_caps() accesses the per-CPU
> audit_cache using get_cpu_var(), which only disables preemption:
>
> security/apparmor/capability.c:audit_caps() {
> ...
> ent = &get_cpu_var(audit_cache);
> if (ad->subj_cred == ent->ad_subj_cred &&
> ktime_get_ns() <= ent->ktime_ns_expiration[cap]) {
> ...
> } else {
> put_cred(ent->ad_subj_cred);
> ent->ad_subj_cred = get_cred(ad->subj_cred);
> ent->ktime_ns_expiration[cap] = ...;
> }
> put_cpu_var(audit_cache);
> ...
> }
>
> If an IRQ or NMI invokes get_user_page_fast_only() while the interrupted
> context is inside audit_caps() on the same CPU, both contexts can race on
> ent->ad_subj_cred and cause a double put_cred().
>
> 4. In kernel/capability.c, ns_capable_common() updates current->flags
> non-atomically:
>
> kernel/capability.c:ns_capable_common() {
> ...
> capable = security_capable(current_cred(), ns, cap, opts);
> if (capable == 0) {
> current->flags |= PF_SUPERPRIV;
> return true;
> }
> ...
> }
>
> When called from hardirq or NMI context, this mutates the interrupted
> task's flags and can race with process-context updates to current->flags.
>
> Should try_get_folio() avoid calling capable() in fast GUP (for example, by
> falling back to slow GUP once the folio refcount reaches
> FOLIO_REF_COUNT_LIMIT)?
What a minefiled :)
Best to throw in something like
if (!in_task() || irqs_disabled())
true;
In the (new) slow helper to just reject admin reserves in such
context.
--
Cheers,
David
next prev parent reply other threads:[~2026-11-06 23:22 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
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-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 21:23 ` David Hildenbrand (Arm)
2026-11-06 12:38 ` Kiryl Shutsemau
2026-11-06 20:54 ` David Hildenbrand (Arm)
2026-11-06 23:25 ` David Hildenbrand (Arm)
2026-11-06 13:11 ` sashiko-bot
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 21:57 ` David Hildenbrand (Arm)
2026-11-06 17:58 ` Josef Bacik
2026-11-06 20:09 ` David Hildenbrand (Arm)
2026-11-06 20:43 ` Jason Gunthorpe
2026-11-06 20:45 ` David Hildenbrand (Arm)
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
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
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
2026-11-06 22:42 ` David Hildenbrand (Arm)
2026-11-06 13:11 ` sashiko-bot
2026-11-06 22:50 ` David Hildenbrand (Arm) [this message]
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)
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=d4559f3c-dc6b-41c3-92ac-8ae0d07ccfcb@kernel.org \
--to=david@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=aneesh.kumar@kernel.org \
--cc=apopple@nvidia.com \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=byungchul@sk.com \
--cc=dev.jain@arm.com \
--cc=gourry@gourry.net \
--cc=hannes@cmpxchg.org \
--cc=hughd@google.com \
--cc=jack@suse.cz \
--cc=jgg@ziepe.ca \
--cc=jhubbard@nvidia.com \
--cc=joro@8bytes.org \
--cc=joshua.hahnjy@gmail.com \
--cc=kas@kernel.org \
--cc=kevin.tian@intel.com \
--cc=lance.yang@linux.dev \
--cc=liam@infradead.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=matthew.brost@intel.com \
--cc=mhocko@suse.com \
--cc=nico.pache@linux.dev \
--cc=npiggin@gmail.com \
--cc=peterx@redhat.com \
--cc=peterz@infradead.org \
--cc=riel@surriel.com \
--cc=robin.murphy@arm.com \
--cc=rppt@kernel.org \
--cc=ryan.roberts@arm.com \
--cc=sashiko-reviews@lists.linux.dev \
--cc=songliubraving@fb.com \
--cc=steven.sistare@oracle.com \
--cc=surenb@google.com \
--cc=usama.arif@linux.dev \
--cc=vbabka@kernel.org \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.