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-add-bpf_stream_print_stack-kfunc'

Emil Tsalapatis says:

====================
bpf: Add bpf_stream_print_stack kfunc

Add a new bpf_stream_print_stack kfunc for printing a BPF program stack
into a BPF stream. Update the verifier to allow the new kfunc to be
called with BPF spinlocks held, along with bpf_stream_vprintk.

Patchset spun out of the larger libarena + ASAN patchset.
(https://lore.kernel.org/bpf/20260127181610.86376-1-emil@etsalapatis.com/)

Changeset:
- Update bpf_stream_print_stack to take stream_id arg (Kumar)
- Added selftest for the bpf_stream_print_stack
- Add selftest for calling the streams kfuncs under lock

v2->v1: (https://lore.kernel.org/bpf/20260202193311.446717-1-emil@etsalapatis.com/)
- Updated Signed-off-by to be consistent with past submissions
- Updated From email to be consistent with Signed-off-by

Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>
====================

Link: https://patch.msgid.link/20260203180424.14057-1-emil@etsalapatis.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+85 -1
+1
kernel/bpf/helpers.c
··· 4562 4562 BTF_ID_FLAGS(func, bpf_cgroup_read_xattr, KF_RCU) 4563 4563 #endif 4564 4564 BTF_ID_FLAGS(func, bpf_stream_vprintk, KF_IMPLICIT_ARGS) 4565 + BTF_ID_FLAGS(func, bpf_stream_print_stack, KF_IMPLICIT_ARGS) 4565 4566 BTF_ID_FLAGS(func, bpf_task_work_schedule_signal, KF_IMPLICIT_ARGS) 4566 4567 BTF_ID_FLAGS(func, bpf_task_work_schedule_resume, KF_IMPLICIT_ARGS) 4567 4568 BTF_ID_FLAGS(func, bpf_dynptr_from_file)
+19
kernel/bpf/stream.c
··· 245 245 return ret; 246 246 } 247 247 248 + /* Directly trigger a stack dump from the program. */ 249 + __bpf_kfunc int bpf_stream_print_stack(int stream_id, struct bpf_prog_aux *aux) 250 + { 251 + struct bpf_stream_stage ss; 252 + struct bpf_prog *prog; 253 + 254 + /* Make sure the stream ID is valid. */ 255 + if (!bpf_stream_get(stream_id, aux)) 256 + return -ENOENT; 257 + 258 + prog = aux->main_prog_aux->prog; 259 + 260 + bpf_stream_stage(ss, prog, stream_id, ({ 261 + bpf_stream_dump_stack(ss); 262 + })); 263 + 264 + return 0; 265 + } 266 + 248 267 __bpf_kfunc_end_defs(); 249 268 250 269 /* Added kfunc to common_btf_ids */
+12 -1
kernel/bpf/verifier.c
··· 12455 12455 KF_bpf_arena_free_pages, 12456 12456 KF_bpf_arena_reserve_pages, 12457 12457 KF_bpf_session_is_return, 12458 + KF_bpf_stream_vprintk, 12459 + KF_bpf_stream_print_stack, 12458 12460 }; 12459 12461 12460 12462 BTF_ID_LIST(special_kfunc_list) ··· 12535 12533 BTF_ID(func, bpf_arena_free_pages) 12536 12534 BTF_ID(func, bpf_arena_reserve_pages) 12537 12535 BTF_ID(func, bpf_session_is_return) 12536 + BTF_ID(func, bpf_stream_vprintk) 12537 + BTF_ID(func, bpf_stream_print_stack) 12538 12538 12539 12539 static bool is_task_work_add_kfunc(u32 func_id) 12540 12540 { ··· 12981 12977 btf_id == special_kfunc_list[KF_bpf_arena_reserve_pages]; 12982 12978 } 12983 12979 12980 + static bool is_bpf_stream_kfunc(u32 btf_id) 12981 + { 12982 + return btf_id == special_kfunc_list[KF_bpf_stream_vprintk] || 12983 + btf_id == special_kfunc_list[KF_bpf_stream_print_stack]; 12984 + } 12985 + 12984 12986 static bool kfunc_spin_allowed(u32 btf_id) 12985 12987 { 12986 12988 return is_bpf_graph_api_kfunc(btf_id) || is_bpf_iter_num_api_kfunc(btf_id) || 12987 - is_bpf_res_spin_lock_kfunc(btf_id) || is_bpf_arena_kfunc(btf_id); 12989 + is_bpf_res_spin_lock_kfunc(btf_id) || is_bpf_arena_kfunc(btf_id) || 12990 + is_bpf_stream_kfunc(btf_id); 12988 12991 } 12989 12992 12990 12993 static bool is_sync_callback_calling_kfunc(u32 btf_id)
+53
tools/testing/selftests/bpf/progs/stream.c
··· 42 42 u64 fault_addr; 43 43 void *arena_ptr; 44 44 45 + #define private(name) SEC(".bss." #name) __hidden __attribute__((aligned(8))) 46 + 47 + private(STREAM) struct bpf_spin_lock block; 48 + 45 49 SEC("syscall") 46 50 __success __retval(0) 47 51 int stream_exhaust(void *ctx) ··· 237 233 bpf_timer_start(arr_timer, 0, 0); 238 234 return 0; 239 235 } 236 + 237 + SEC("syscall") 238 + __arch_x86_64 239 + __arch_arm64 240 + __success __retval(0) 241 + __stderr("CPU: {{[0-9]+}} UID: 0 PID: {{[0-9]+}} Comm: {{.*}}") 242 + __stderr("Call trace:\n" 243 + "{{([a-zA-Z_][a-zA-Z0-9_]*\\+0x[0-9a-fA-F]+/0x[0-9a-fA-F]+\n" 244 + "|[ \t]+[^\n]+\n)*}}") 245 + int stream_print_stack_kfunc(void *ctx) 246 + { 247 + return bpf_stream_print_stack(BPF_STDERR); 248 + } 249 + 250 + SEC("syscall") 251 + __success __retval(-2) 252 + int stream_print_stack_invalid_id(void *ctx) 253 + { 254 + /* Try to pass an invalid stream ID. */ 255 + return bpf_stream_print_stack((enum bpf_stream_id)0xbadcafe); 256 + } 257 + 258 + SEC("syscall") 259 + __arch_x86_64 260 + __arch_arm64 261 + __success __retval(0) 262 + __stdout(_STR) 263 + __stderr("CPU: {{[0-9]+}} UID: 0 PID: {{[0-9]+}} Comm: {{.*}}") 264 + __stderr("Call trace:\n" 265 + "{{([a-zA-Z_][a-zA-Z0-9_]*\\+0x[0-9a-fA-F]+/0x[0-9a-fA-F]+\n" 266 + "|[ \t]+[^\n]+\n)*}}") 267 + int stream_print_kfuncs_locked(void *ctx) 268 + { 269 + int ret; 270 + 271 + bpf_spin_lock(&block); 272 + 273 + ret = bpf_stream_printk(BPF_STDOUT, _STR); 274 + if (ret) 275 + goto out; 276 + 277 + ret = bpf_stream_print_stack(BPF_STDERR); 278 + 279 + out: 280 + bpf_spin_unlock(&block); 281 + 282 + return ret; 283 + } 284 + 240 285 241 286 char _license[] SEC("license") = "GPL";