From: Yuan Chen <[email protected]>
arena_free_pages() and arena_free_worker() ignore range_tree_set()
errors and proceed to clear PTEs and free pages, even though the range
tree still considers the range allocated. The range then becomes
permanently unavailable.
Check the return value: in arena_free_pages() abort the free on error;
in arena_free_worker() move range_tree_set() before PTE clearing and
skip the span on error.
Fixes: b795379757eb ("bpf: Introduce range_tree data structure and use it in bpf arena")
Signed-off-by: Yuan Chen <[email protected]>
---
kernel/bpf/arena.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/kernel/bpf/arena.c b/kernel/bpf/arena.c
index 555ee2531ef9..30745da9277b 100644
--- a/kernel/bpf/arena.c
+++ b/kernel/bpf/arena.c
@@ -881,7 +881,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 +1009,17 @@ 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);
--
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.