From: sashiko-bot@kernel.org
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH 2/3] bpf: arena: use page_ref_count() instead of page_mapped() in arena_free_pages()
Date: Mon, 27 Apr 2026 20:14:41 +0000 [thread overview]
Message-ID: <20260427201442.97A0AC19425@smtp.kernel.org> (raw)
In-Reply-To: <20260427-page_mapped-v1-2-e89c3592c74c@kernel.org>
Sashiko AI review found 2 potential issue(s):
- [Critical] Replacing `page_mapped()` with `page_ref_count() > 1` removes the synchronous mapcount check, allowing the lockless `zap_pages()` page table walk to execute concurrently with `free_pgtables()` during `munmap()`, leading to a page table use-after-free.
- [Medium] The patch incorrectly uses a lifetime counter (`page_ref_count`) as a semantic indicator to determine if a page is mapped in user space, violating MM guidelines.
--
commit 7d590c0af75e613441c8863162be310388ecc992
Author: David Hildenbrand (Arm) <david@kernel.org>
bpf: arena: use page_ref_count() instead of page_mapped() in arena_free_pages()
This commit changes the heuristic in arena_free_pages() to use
page_ref_count(page) > 1 instead of page_mapped() to determine whether
to call zap_pages(). This avoids mapcount usage as pages will not have
a mapcount in the future.
> diff --git a/kernel/bpf/arena.c b/kernel/bpf/arena.c
> index 802656c6fd3c..608c55c260bc 100644
> --- a/kernel/bpf/arena.c
> +++ b/kernel/bpf/arena.c
[ ... ]
> @@ -729,7 +729,7 @@ static void arena_free_pages(struct bpf_arena *arena, long uaddr, long page_cnt,
>
> llist_for_each_safe(pos, t, __llist_del_all(&free_pages)) {
> page = llist_entry(pos, struct page, pcp_llist);
> - if (page_cnt == 1 && page_mapped(page)) /* mapped by some user process */
> + if (page_cnt == 1 && page_ref_count(page) > 1) /* maybe mapped by user space */
Can this lead to a page table use-after-free during concurrent munmap()?
zap_pages() iterates over arena->vma_list and walks user page tables locklessly.
During a concurrent munmap(), unmap_region() executes unmap_vmas() (which drops
mapcounts), free_pgtables() (which unlinks and frees page tables), and finally
tlb_finish_mmu() (which drops the batched page refcounts via mmu_gather).
The VMA is only removed from arena->vma_list later during arena_vm_close(),
meaning it is still visible to zap_pages() during free_pgtables().
Since mmu_gather retains the page reference until tlb_finish_mmu(),
page_ref_count(page) > 1 will remain true during free_pgtables().
With the old page_mapped() check, it would correctly evaluate to false because
unmap_vmas() had already dropped the mapcount to 0. It appears this change
could allow zap_pages() to walk page tables while they are actively being freed.
This could also be forced by artificially inflating the refcount using GUP pins.
Also, does this use of page_ref_count() conflict with the MM guideline that
refcount should be treated as a lifetime counter rather than a semantic
indicator?
Speculative references (like GUP pins or page_idle) can transiently inflate
the refcount independently of user space mappings.
> /* Optimization for the common case of page_cnt==1:
> * If page wasn't mapped into some user vma there
> * is no need to call zap_pages which is slow. When
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260427-page_mapped-v1-0-e89c3592c74c@kernel.org?part=2
next prev parent reply other threads:[~2026-04-27 20:14 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-27 11:43 [PATCH 0/3] mm: remove page_mapped() David Hildenbrand (Arm)
2026-04-27 11:43 ` [PATCH 1/3] sh: use folio_mapped() instead of page_mapped() in sh4_flush_cache_page() David Hildenbrand (Arm)
2026-04-27 12:43 ` Matthew Wilcox
2026-04-27 11:43 ` [PATCH 2/3] bpf: arena: use page_ref_count() instead of page_mapped() in arena_free_pages() David Hildenbrand (Arm)
2026-04-27 12:17 ` Andrew Morton
2026-04-27 15:00 ` Alexei Starovoitov
2026-04-27 15:15 ` Andrew Morton
2026-04-27 15:27 ` Alexei Starovoitov
2026-04-28 8:16 ` David Hildenbrand (Arm)
2026-04-28 16:58 ` Alexei Starovoitov
2026-04-28 19:38 ` David Hildenbrand (Arm)
2026-04-28 8:44 ` Vlastimil Babka (SUSE)
2026-04-27 13:00 ` Matthew Wilcox
2026-04-27 20:14 ` sashiko-bot [this message]
2026-04-27 11:43 ` [PATCH 3/3] mm: remove page_mapped() David Hildenbrand (Arm)
2026-04-27 13:12 ` Matthew Wilcox
2026-04-27 13:21 ` Andrew Morton
2026-04-27 13:23 ` David Hildenbrand (Arm)
2026-04-27 14:42 ` Breno Leitao
2026-04-27 14:59 ` Matthew Wilcox
2026-04-27 20:59 ` [PATCH 0/3] " David Hildenbrand (Arm)
2026-04-27 21:38 ` Alexei Starovoitov
2026-04-28 5:37 ` 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=20260427201442.97A0AC19425@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=sashiko@lists.linux.dev \
/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.