mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	bpf: Add dump_stack() analogue to print to BPF stderr
Introduce a kernel function which is the analogue of dump_stack() printing some useful information and the stack trace. This is not exposed to BPF programs yet, but can be made available in the future. When we have a program counter for a BPF program in the stack trace, also additionally output the filename and line number to make the trace helpful. The rest of the trace can be passed into ./decode_stacktrace.sh to obtain the line numbers for kernel symbols. Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Link: https://lore.kernel.org/r/20250703204818.925464-7-memxor@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
		
							parent
							
								
									f0c53fd4a7
								
							
						
					
					
						commit
						d7c431cafc
					
				
					 2 changed files with 50 additions and 0 deletions
				
			
		|  | @ -3616,8 +3616,10 @@ __printf(2, 3) | ||||||
| int bpf_stream_stage_printk(struct bpf_stream_stage *ss, const char *fmt, ...); | int bpf_stream_stage_printk(struct bpf_stream_stage *ss, const char *fmt, ...); | ||||||
| int bpf_stream_stage_commit(struct bpf_stream_stage *ss, struct bpf_prog *prog, | int bpf_stream_stage_commit(struct bpf_stream_stage *ss, struct bpf_prog *prog, | ||||||
| 			    enum bpf_stream_id stream_id); | 			    enum bpf_stream_id stream_id); | ||||||
|  | int bpf_stream_stage_dump_stack(struct bpf_stream_stage *ss); | ||||||
| 
 | 
 | ||||||
| #define bpf_stream_printk(ss, ...) bpf_stream_stage_printk(&ss, __VA_ARGS__) | #define bpf_stream_printk(ss, ...) bpf_stream_stage_printk(&ss, __VA_ARGS__) | ||||||
|  | #define bpf_stream_dump_stack(ss) bpf_stream_stage_dump_stack(&ss) | ||||||
| 
 | 
 | ||||||
| #define bpf_stream_stage(ss, prog, stream_id, expr)            \ | #define bpf_stream_stage(ss, prog, stream_id, expr)            \ | ||||||
| 	({                                                     \ | 	({                                                     \ | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| /* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */ | /* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */ | ||||||
| 
 | 
 | ||||||
| #include <linux/bpf.h> | #include <linux/bpf.h> | ||||||
|  | #include <linux/filter.h> | ||||||
| #include <linux/bpf_mem_alloc.h> | #include <linux/bpf_mem_alloc.h> | ||||||
| #include <linux/percpu.h> | #include <linux/percpu.h> | ||||||
| #include <linux/refcount.h> | #include <linux/refcount.h> | ||||||
|  | @ -476,3 +477,50 @@ int bpf_stream_stage_commit(struct bpf_stream_stage *ss, struct bpf_prog *prog, | ||||||
| 	llist_add_batch(head, tail, &stream->log); | 	llist_add_batch(head, tail, &stream->log); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | struct dump_stack_ctx { | ||||||
|  | 	struct bpf_stream_stage *ss; | ||||||
|  | 	int err; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static bool dump_stack_cb(void *cookie, u64 ip, u64 sp, u64 bp) | ||||||
|  | { | ||||||
|  | 	struct dump_stack_ctx *ctxp = cookie; | ||||||
|  | 	const char *file = "", *line = ""; | ||||||
|  | 	struct bpf_prog *prog; | ||||||
|  | 	int num, ret; | ||||||
|  | 
 | ||||||
|  | 	rcu_read_lock(); | ||||||
|  | 	prog = bpf_prog_ksym_find(ip); | ||||||
|  | 	rcu_read_unlock(); | ||||||
|  | 	if (prog) { | ||||||
|  | 		ret = bpf_prog_get_file_line(prog, ip, &file, &line, &num); | ||||||
|  | 		if (ret < 0) | ||||||
|  | 			goto end; | ||||||
|  | 		ctxp->err = bpf_stream_stage_printk(ctxp->ss, "%pS\n  %s @ %s:%d\n", | ||||||
|  | 						    (void *)ip, line, file, num); | ||||||
|  | 		return !ctxp->err; | ||||||
|  | 	} | ||||||
|  | end: | ||||||
|  | 	ctxp->err = bpf_stream_stage_printk(ctxp->ss, "%pS\n", (void *)ip); | ||||||
|  | 	return !ctxp->err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int bpf_stream_stage_dump_stack(struct bpf_stream_stage *ss) | ||||||
|  | { | ||||||
|  | 	struct dump_stack_ctx ctx = { .ss = ss }; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	ret = bpf_stream_stage_printk(ss, "CPU: %d UID: %d PID: %d Comm: %s\n", | ||||||
|  | 				      raw_smp_processor_id(), __kuid_val(current_real_cred()->euid), | ||||||
|  | 				      current->pid, current->comm); | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | 	ret = bpf_stream_stage_printk(ss, "Call trace:\n"); | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | 	arch_bpf_stack_walk(dump_stack_cb, &ctx); | ||||||
|  | 	if (ctx.err) | ||||||
|  | 		return ctx.err; | ||||||
|  | 	return bpf_stream_stage_printk(ss, "\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Kumar Kartikeya Dwivedi
						Kumar Kartikeya Dwivedi