[PATCH bpf-next v5 0/3] bpf, arena: fix range_tree consistency on allocation failure

From: chenyuan_fl

Date: Wed Sep 02 2026 - 05:48:49 EST


From: Yuan Chen <chenyuan@xxxxxxxxxx>

The arena range tree can be left inconsistent when kmalloc_nolock()
fails mid-operation. Patch 1 fixes range_tree_clear(), patch 2 fixes
range_tree_set(), patch 3 makes the arena free paths handle
range_tree_set() failures, checks the return value in
arena_alloc_pages()'s partial-allocation error path, and makes
arena_map_free() drain the deferred-free machinery safely now that the
worker can requeue failed spans and queue irq_work on retry.

Changes in v5:
- arena_map_free(): set a dying flag and steal orphaned spans before
draining, and drain with flush_work() + irq_work_sync() +
flush_work(). The worker retry queues arena->free_irq, which the
old irq_work_sync() + flush_work() order could miss: the irq_work
fired after the arena was freed and its callback scheduled
free_work on freed memory.
- arena_map_free(): retry the spinlock acquisition a bounded number
of times (-EDEADLK is not retried) and WARN with the error code,
instead of a bare WARN_ON_ONCE(1) and an immediate leak of the
arena.
- range_tree_set(): reword the comment describing the two lookups,
as suggested by Alexei Starovoitov. The pre-clear probe only
decides whether a fresh node must be allocated, so that -ENOMEM
leaves the tree unmodified; the post-clear lookup fetches the
merge handles without depending on how range_tree_clear()
truncates overlapping nodes.

Changes in v4:
- arena_free_worker(): keep a span whose range_tree_set() failed on
arena->free_spans and retry it on a later worker run, instead of
leaving it in the drained list where the second loop would still
zap user VMAs and free the span (dropping the free request), as
pointed out by Emil Tsalapatis.

Changes in v3:
- Check range_tree_set() return value in arena_alloc_pages()'s error
path, which restores the unpopulated tail of a partially allocated
range (previously ignored), as pointed out in review.

Changes in v2:
- Fix multi-line comment style in patches 1 and 3 (opening /* on its
own line), as pointed out in review.

Note: arena_vm_fault()'s two recovery paths (restoring the range to the
free tree after allocation/mapping failure) also call range_tree_set()
without checking the return value; that is addressed in a separate
series.

Yuan Chen (3):
bpf, arena: fix range_tree_clear inconsistency on kmalloc_nolock
failure
bpf, arena: fix range_tree_set inconsistency on kmalloc_nolock failure
bpf, arena: handle range_tree_set failures in alloc/free paths

kernel/bpf/arena.c | 95 ++++++++++++++++++++++++++++++++++----
kernel/bpf/range_tree.c | 61 +++++++++++++++++-------
2 files changed, 132 insertions(+), 24 deletions(-)

--
2.54.0