mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	bpf: Add bpf_prog iterator
It's mostly a copy paste of commit 6086d29def ("bpf: Add bpf_map iterator")
that is use to implement bpf_seq_file opreations to traverse all bpf programs.
v1->v2: Tweak to use build time btf_id
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Yonghong Song <yhs@fb.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
			
			
This commit is contained in:
		
							parent
							
								
									3f9969f2c0
								
							
						
					
					
						commit
						a228a64fc1
					
				
					 4 changed files with 124 additions and 1 deletions
				
			
		|  | @ -1117,6 +1117,7 @@ int  generic_map_delete_batch(struct bpf_map *map, | |||
| 			      const union bpf_attr *attr, | ||||
| 			      union bpf_attr __user *uattr); | ||||
| struct bpf_map *bpf_map_get_curr_or_next(u32 *id); | ||||
| struct bpf_prog *bpf_prog_get_curr_or_next(u32 *id); | ||||
| 
 | ||||
| extern int sysctl_unprivileged_bpf_disabled; | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| obj-y := core.o | ||||
| CFLAGS_core.o += $(call cc-disable-warning, override-init) | ||||
| 
 | ||||
| obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o bpf_iter.o map_iter.o task_iter.o | ||||
| obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o bpf_iter.o map_iter.o task_iter.o prog_iter.o | ||||
| obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o | ||||
| obj-$(CONFIG_BPF_SYSCALL) += local_storage.o queue_stack_maps.o ringbuf.o | ||||
| obj-$(CONFIG_BPF_SYSCALL) += disasm.o | ||||
|  |  | |||
							
								
								
									
										103
									
								
								kernel/bpf/prog_iter.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								kernel/bpf/prog_iter.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,103 @@ | |||
| // SPDX-License-Identifier: GPL-2.0-only
 | ||||
| /* Copyright (c) 2020 Facebook */ | ||||
| #include <linux/bpf.h> | ||||
| #include <linux/fs.h> | ||||
| #include <linux/filter.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/btf_ids.h> | ||||
| 
 | ||||
| struct bpf_iter_seq_prog_info { | ||||
| 	u32 prog_id; | ||||
| }; | ||||
| 
 | ||||
| static void *bpf_prog_seq_start(struct seq_file *seq, loff_t *pos) | ||||
| { | ||||
| 	struct bpf_iter_seq_prog_info *info = seq->private; | ||||
| 	struct bpf_prog *prog; | ||||
| 
 | ||||
| 	prog = bpf_prog_get_curr_or_next(&info->prog_id); | ||||
| 	if (!prog) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	if (*pos == 0) | ||||
| 		++*pos; | ||||
| 	return prog; | ||||
| } | ||||
| 
 | ||||
| static void *bpf_prog_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||||
| { | ||||
| 	struct bpf_iter_seq_prog_info *info = seq->private; | ||||
| 
 | ||||
| 	++*pos; | ||||
| 	++info->prog_id; | ||||
| 	bpf_prog_put((struct bpf_prog *)v); | ||||
| 	return bpf_prog_get_curr_or_next(&info->prog_id); | ||||
| } | ||||
| 
 | ||||
| struct bpf_iter__bpf_prog { | ||||
| 	__bpf_md_ptr(struct bpf_iter_meta *, meta); | ||||
| 	__bpf_md_ptr(struct bpf_prog *, prog); | ||||
| }; | ||||
| 
 | ||||
| DEFINE_BPF_ITER_FUNC(bpf_prog, struct bpf_iter_meta *meta, struct bpf_prog *prog) | ||||
| 
 | ||||
| static int __bpf_prog_seq_show(struct seq_file *seq, void *v, bool in_stop) | ||||
| { | ||||
| 	struct bpf_iter__bpf_prog ctx; | ||||
| 	struct bpf_iter_meta meta; | ||||
| 	struct bpf_prog *prog; | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	ctx.meta = &meta; | ||||
| 	ctx.prog = v; | ||||
| 	meta.seq = seq; | ||||
| 	prog = bpf_iter_get_info(&meta, in_stop); | ||||
| 	if (prog) | ||||
| 		ret = bpf_iter_run_prog(prog, &ctx); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static int bpf_prog_seq_show(struct seq_file *seq, void *v) | ||||
| { | ||||
| 	return __bpf_prog_seq_show(seq, v, false); | ||||
| } | ||||
| 
 | ||||
| static void bpf_prog_seq_stop(struct seq_file *seq, void *v) | ||||
| { | ||||
| 	if (!v) | ||||
| 		(void)__bpf_prog_seq_show(seq, v, true); | ||||
| 	else | ||||
| 		bpf_prog_put((struct bpf_prog *)v); | ||||
| } | ||||
| 
 | ||||
| static const struct seq_operations bpf_prog_seq_ops = { | ||||
| 	.start	= bpf_prog_seq_start, | ||||
| 	.next	= bpf_prog_seq_next, | ||||
| 	.stop	= bpf_prog_seq_stop, | ||||
| 	.show	= bpf_prog_seq_show, | ||||
| }; | ||||
| 
 | ||||
| BTF_ID_LIST(btf_bpf_prog_id) | ||||
| BTF_ID(struct, bpf_prog) | ||||
| 
 | ||||
| static struct bpf_iter_reg bpf_prog_reg_info = { | ||||
| 	.target			= "bpf_prog", | ||||
| 	.seq_ops		= &bpf_prog_seq_ops, | ||||
| 	.init_seq_private	= NULL, | ||||
| 	.fini_seq_private	= NULL, | ||||
| 	.seq_priv_size		= sizeof(struct bpf_iter_seq_prog_info), | ||||
| 	.ctx_arg_info_size	= 1, | ||||
| 	.ctx_arg_info		= { | ||||
| 		{ offsetof(struct bpf_iter__bpf_prog, prog), | ||||
| 		  PTR_TO_BTF_ID_OR_NULL }, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| static int __init bpf_prog_iter_init(void) | ||||
| { | ||||
| 	bpf_prog_reg_info.ctx_arg_info[0].btf_id = *btf_bpf_prog_id; | ||||
| 	return bpf_iter_reg_target(&bpf_prog_reg_info); | ||||
| } | ||||
| 
 | ||||
| late_initcall(bpf_prog_iter_init); | ||||
|  | @ -3044,6 +3044,25 @@ struct bpf_map *bpf_map_get_curr_or_next(u32 *id) | |||
| 	return map; | ||||
| } | ||||
| 
 | ||||
| struct bpf_prog *bpf_prog_get_curr_or_next(u32 *id) | ||||
| { | ||||
| 	struct bpf_prog *prog; | ||||
| 
 | ||||
| 	spin_lock_bh(&prog_idr_lock); | ||||
| again: | ||||
| 	prog = idr_get_next(&prog_idr, id); | ||||
| 	if (prog) { | ||||
| 		prog = bpf_prog_inc_not_zero(prog); | ||||
| 		if (IS_ERR(prog)) { | ||||
| 			(*id)++; | ||||
| 			goto again; | ||||
| 		} | ||||
| 	} | ||||
| 	spin_unlock_bh(&prog_idr_lock); | ||||
| 
 | ||||
| 	return prog; | ||||
| } | ||||
| 
 | ||||
| #define BPF_PROG_GET_FD_BY_ID_LAST_FIELD prog_id | ||||
| 
 | ||||
| struct bpf_prog *bpf_prog_by_id(u32 id) | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Alexei Starovoitov
						Alexei Starovoitov