Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'bpf-verifier-allow-calling-arena-functions-when-holding-bpf-lock'

Emil Tsalapatis says:

====================
bpf/verifier: Allow calling arena functions when holding BPF lock

BPF arena-related kfuncs now cannot sleep, so they are safe to call
while holding a spinlock. However, the verifier still rejects
programs that do so. Update the verifier to allow arena kfunc
calls while holding a lock.

Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>

Changes v1->v2: (https://lore.kernel.org/r/20260106-arena-under-lock-v1-0-6ca9c121d826@etsalapatis.com)
- Added patch to account for active locks in_sleepable_context() (AI)
====================

Link: https://patch.msgid.link/20260106-arena-under-lock-v2-0-378e9eab3066@etsalapatis.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+49 -1
+11 -1
kernel/bpf/verifier.c
··· 11466 11466 { 11467 11467 return !env->cur_state->active_rcu_locks && 11468 11468 !env->cur_state->active_preempt_locks && 11469 + !env->cur_state->active_locks && 11469 11470 !env->cur_state->active_irq_id && 11470 11471 in_sleepable(env); 11471 11472 } ··· 12373 12372 KF_bpf_task_work_schedule_resume_impl, 12374 12373 KF_bpf_arena_alloc_pages, 12375 12374 KF_bpf_arena_free_pages, 12375 + KF_bpf_arena_reserve_pages, 12376 12376 }; 12377 12377 12378 12378 BTF_ID_LIST(special_kfunc_list) ··· 12450 12448 BTF_ID(func, bpf_task_work_schedule_resume_impl) 12451 12449 BTF_ID(func, bpf_arena_alloc_pages) 12452 12450 BTF_ID(func, bpf_arena_free_pages) 12451 + BTF_ID(func, bpf_arena_reserve_pages) 12453 12452 12454 12453 static bool is_task_work_add_kfunc(u32 func_id) 12455 12454 { ··· 12886 12883 btf_id == special_kfunc_list[KF_bpf_res_spin_unlock_irqrestore]; 12887 12884 } 12888 12885 12886 + static bool is_bpf_arena_kfunc(u32 btf_id) 12887 + { 12888 + return btf_id == special_kfunc_list[KF_bpf_arena_alloc_pages] || 12889 + btf_id == special_kfunc_list[KF_bpf_arena_free_pages] || 12890 + btf_id == special_kfunc_list[KF_bpf_arena_reserve_pages]; 12891 + } 12892 + 12889 12893 static bool kfunc_spin_allowed(u32 btf_id) 12890 12894 { 12891 12895 return is_bpf_graph_api_kfunc(btf_id) || is_bpf_iter_num_api_kfunc(btf_id) || 12892 - is_bpf_res_spin_lock_kfunc(btf_id); 12896 + is_bpf_res_spin_lock_kfunc(btf_id) || is_bpf_arena_kfunc(btf_id); 12893 12897 } 12894 12898 12895 12899 static bool is_sync_callback_calling_kfunc(u32 btf_id)
+38
tools/testing/selftests/bpf/progs/verifier_arena.c
··· 10 10 #include "bpf_experimental.h" 11 11 #include "bpf_arena_common.h" 12 12 13 + #define private(name) SEC(".bss." #name) __hidden __attribute__((aligned(8))) 14 + 13 15 struct { 14 16 __uint(type, BPF_MAP_TYPE_ARENA); 15 17 __uint(map_flags, BPF_F_MMAPABLE); ··· 441 439 return 0; 442 440 } 443 441 442 + private(ARENA_TESTS) struct bpf_spin_lock arena_bpf_test_lock; 443 + 444 + /* Use the arena kfunc API while under a BPF lock. */ 445 + SEC("syscall") 446 + __success __retval(0) 447 + int arena_kfuncs_under_bpf_lock(void *ctx) 448 + { 449 + #if defined(__BPF_FEATURE_ADDR_SPACE_CAST) 450 + char __arena *page; 451 + int ret; 452 + 453 + bpf_spin_lock(&arena_bpf_test_lock); 454 + 455 + /* Get a separate region of the arena. */ 456 + page = arena_base(&arena); 457 + ret = bpf_arena_reserve_pages(&arena, page, 1); 458 + if (ret) { 459 + bpf_spin_unlock(&arena_bpf_test_lock); 460 + return 1; 461 + } 462 + 463 + bpf_arena_free_pages(&arena, page, 1); 464 + 465 + page = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0); 466 + if (!page) { 467 + bpf_spin_unlock(&arena_bpf_test_lock); 468 + return 2; 469 + } 470 + 471 + bpf_arena_free_pages(&arena, page, 1); 472 + 473 + bpf_spin_unlock(&arena_bpf_test_lock); 474 + #endif 475 + 476 + return 0; 477 + } 444 478 char _license[] SEC("license") = "GPL";