From: "Emil Tsalapatis" <emil@etsalapatis.com>
To: <chenyuan_fl@163.com>, <bpf@vger.kernel.org>
Cc: <linux-kernel@vger.kernel.org>,
"Alexei Starovoitov" <ast@kernel.org>,
"Daniel Borkmann" <daniel@iogearbox.net>,
"Andrii Nakryiko" <andrii@kernel.org>,
"Eduard Zingerman" <eddyz87@gmail.com>,
"Kumar Kartikeya Dwivedi" <memxor@gmail.com>,
"Martin KaFai Lau" <martin.lau@linux.dev>,
"Song Liu" <song@kernel.org>,
"Yonghong Song" <yonghong.song@linux.dev>,
"Jiri Olsa" <jolsa@kernel.org>,
"Emil Tsalapatis" <emil@etsalapatis.com>,
"Ihor Solodrai" <ihor.solodrai@linux.dev>,
"Yuan Chen" <chenyuan@kylinos.cn>
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 13:30:00 -0400 [thread overview]
Message-ID: <DKT3K5ONBQO6.16J47HLN6HS6@etsalapatis.com> (raw)
In-Reply-To: <20260810134800.2875487-4-chenyuan_fl@163.com>
On Mon Aug 10, 2026 at 9:48 AM EDT, chenyuan_fl wrote:
> From: Yuan Chen <chenyuan@kylinos.cn>
>
> arena_free_pages() and arena_free_worker() now handle range_tree_set()
> errors. arena_free_pages() aborts the free on error, and
> arena_free_worker() moves range_tree_set() before PTE clearing so that a
> failed tree update leaves the PTEs intact instead of freeing pages that
> the arena free tree does not track.
>
> Also check the range_tree_set() return value in arena_alloc_pages()'s
> error path, which restores the unpopulated tail of a partially allocated
> range; log a warning instead of silently leaking the virtual range when
> the tree update fails.
>
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
The fact we can fail to free a page because of an allocation failure is
...not great. Especially considering the failure is silent (we can't
turn this into a warning ofc bc it would be triggerable by user error).
Imo this is very close to a silent memory leak, but the only mitigation
I can think of is some kind of retry, and going down that route would get
really messy really fast.
> ---
> kernel/bpf/arena.c | 22 ++++++++++++++++++----
> 1 file changed, 18 insertions(+), 4 deletions(-)
>
> diff --git a/kernel/bpf/arena.c b/kernel/bpf/arena.c
> index 555ee2531ef9..d57a0b617525 100644
> --- a/kernel/bpf/arena.c
> +++ b/kernel/bpf/arena.c
> @@ -766,7 +766,9 @@ static long arena_alloc_pages(struct bpf_arena *arena, long uaddr, long page_cnt
> bpf_map_memcg_exit(old_memcg, new_memcg);
> return clear_lo32(arena->user_vm_start) + uaddr32;
> out:
> - range_tree_set(&arena->rt, pgoff + mapped, page_cnt - mapped);
> + if (range_tree_set(&arena->rt, pgoff + mapped, page_cnt - mapped))
> + pr_warn_ratelimited("bpf_arena: failed to restore free range %ld+%ld after partial alloc\n",
> + pgoff + mapped, page_cnt - mapped);
> raw_res_spin_unlock_irqrestore(&arena->spinlock, flags);
> if (mapped) {
> flush_vmap_cache(kern_vm_start + uaddr32, mapped << PAGE_SHIFT);
> @@ -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;
> + }
>
> 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;
> +
> /* 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);
>
prev parent reply other threads:[~2026-08-19 17:30 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
2026-08-19 17:30 ` Emil Tsalapatis [this message]
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=DKT3K5ONBQO6.16J47HLN6HS6@etsalapatis.com \
--to=emil@etsalapatis.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=chenyuan@kylinos.cn \
--cc=chenyuan_fl@163.com \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=ihor.solodrai@linux.dev \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=song@kernel.org \
--cc=yonghong.song@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.