From: "Emil Tsalapatis" <emil@etsalapatis.com>
To: <sashiko-reviews@lists.linux.dev>, <chenyuan_fl@163.com>
Cc: <bpf@vger.kernel.org>
Subject: Re: [PATCH bpf-next v3 3/3] bpf, arena: check range_tree_set return in arena_free_pages and arena_free_worker
Date: Wed, 19 Aug 2026 15:11:31 -0400 [thread overview]
Message-ID: <DKT5PVZDPTZX.38GSKZBE4TPYR@etsalapatis.com> (raw)
In-Reply-To: <20260810140850.4214E1F000E9@smtp.kernel.org>
On Mon Aug 10, 2026 at 10:08 AM EDT, sashiko-bot wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [High] Physical memory leak in the BPF arena allocation rollback and deferred free paths when `range_tree_set()` fails.
> --
>
> --- Patch [3]: [PATCH bpf-next v3 3/3] bpf, arena: check range_tree_set return in arena_free_pages and arena_free_worker ---
> commit 2ed41c8c8f7aaa211a3d44f83cea88768b2f5819
> Author: Yuan Chen <chenyuan@kylinos.cn>
>
> bpf, arena: check range_tree_set return in arena_free_pages and arena_free_worker
>
> This commit adds error checking for range_tree_set() in the BPF arena
> allocation rollback and free paths. If the tree update fails, it aborts
> the page free operation or skips clearing PTEs to prevent untracked pages.
>
>> diff --git a/kernel/bpf/arena.c b/kernel/bpf/arena.c
>> index 7b6847200b431..1e519c3c229ca 100644
>> --- a/kernel/bpf/arena.c
>> +++ b/kernel/bpf/arena.c
>
> [ ... ]
>
>> @@ -881,7 +883,12 @@ static void arena_free_pages(struct bpf_arena *arena, long uaddr, long page_cnt,
>> if (ret)
>> goto defer;
>>
>> - range_tree_set(&arena->rt, pgoff, page_cnt);
>> + ret = range_tree_set(&arena->rt, pgoff, page_cnt);
>> + if (ret) {
>> + raw_res_spin_unlock_irqrestore(&arena->spinlock, flags);
>> + bpf_map_memcg_exit(old_memcg, new_memcg);
>> + return;
>> + }
>
> [Severity: High]
> Does this early return cause a physical memory leak bounded by the lifetime
> of the BPF map?
>
> If arena_alloc_pages() fails midway due to memory limits, it attempts to
> roll back the partially allocated physical pages by calling
> arena_free_pages(). Under memory pressure, the range_tree_set() call is
> highly likely to fail due to its internal kmalloc_nolock() allocation.
>
> Aborting here leaves the physical pages mapped in the kernel VMA and
> completely orphaned. Exchanging a virtual address space leak for a physical
> memory leak on an error path under OOM conditions worsens memory pressure.
>
> The pre-patch behavior of freeing pages and clearing PTEs appeared safe,
> since bpf_arena_fault_handler() handles unmapped PTEs by mapping the
> scratch_page.
>
Imo this is debatable. If we are at the point where we can't allocate
entries in the range tree, we are close to an OOM anyway and so it is
better to keep the range tree and actual mappings consistent.
>> init_llist_head(&free_pages);
>> cdata.arena = arena;
>
> [ ... ]
>
>> @@ -1004,11 +1011,18 @@ static void arena_free_worker(struct work_struct *work)
>> kaddr = arena_vm_start + s->uaddr;
>> pgoff = compute_pgoff(arena, s->uaddr);
>>
>> + /*
>> + * Mark the range as free before clearing PTEs so that
>> + * if the range tree update fails we leave the PTEs
>> + * intact, avoiding an unrecoverable state where pages
>> + * are freed but the arena free tree does not track them.
>> + */
>> + if (range_tree_set(&arena->rt, pgoff, page_cnt))
>> + continue;
>> +
>
> [Severity: High]
> Can this continue statement permanently leak the physical pages from the
> free system?
>
> When this skips PTE clearing and page collection, the subsequent loop in
> arena_free_worker():
>
> arena_free_worker() {
> ...
> llist_for_each_safe(pos, t, list) {
> s = llist_entry(pos, struct arena_free_span, node);
> ...
> kfree_nolock(s);
> }
> ...
> }
>
> unconditionally destroys the tracking span 's'. This abandons the pages,
> leaving them orphaned rather than avoiding an unrecoverable state.
This, however, seems valid. You can make it so that we do not free
ranges for which we haven't called apply_range_clear_cb.
pw-bot: cr
>
>> /* clear ptes and collect pages in free_pages llist */
>> apply_to_existing_page_range(&init_mm, kaddr, page_cnt << PAGE_SHIFT,
>> apply_range_clear_cb, &cdata);
>> -
>> - range_tree_set(&arena->rt, pgoff, page_cnt);
>> }
>> raw_res_spin_unlock_irqrestore(&arena->spinlock, flags);
next prev parent reply other threads:[~2026-08-19 19:11 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-10 13:47 [PATCH bpf-next v3 0/3] bpf, arena: fix range_tree consistency on allocation failure chenyuan_fl
2026-08-10 13:47 ` [PATCH bpf-next v3 1/3] bpf, arena: fix range_tree_clear inconsistency on kmalloc_nolock failure chenyuan_fl
2026-08-10 14:04 ` sashiko-bot
2026-08-19 17:25 ` Emil Tsalapatis
2026-08-10 13:47 ` [PATCH bpf-next v3 2/3] bpf, arena: fix range_tree_set " chenyuan_fl
2026-08-10 15:10 ` bot+bpf-ci
2026-08-19 17:25 ` Emil Tsalapatis
2026-08-10 13:48 ` [PATCH bpf-next v3 3/3] bpf, arena: check range_tree_set return in arena_free_pages and arena_free_worker chenyuan_fl
2026-08-10 14:08 ` sashiko-bot
2026-08-19 19:11 ` Emil Tsalapatis [this message]
2026-08-19 17:30 ` Emil Tsalapatis
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=DKT5PVZDPTZX.38GSKZBE4TPYR@etsalapatis.com \
--to=emil@etsalapatis.com \
--cc=bpf@vger.kernel.org \
--cc=chenyuan_fl@163.com \
--cc=sashiko-reviews@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.