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, | 			      const union bpf_attr *attr, | ||||||
| 			      union bpf_attr __user *uattr); | 			      union bpf_attr __user *uattr); | ||||||
| struct bpf_map *bpf_map_get_curr_or_next(u32 *id); | 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; | extern int sysctl_unprivileged_bpf_disabled; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| obj-y := core.o | obj-y := core.o | ||||||
| CFLAGS_core.o += $(call cc-disable-warning, override-init) | 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) += 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) += local_storage.o queue_stack_maps.o ringbuf.o | ||||||
| obj-$(CONFIG_BPF_SYSCALL) += disasm.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; | 	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 | #define BPF_PROG_GET_FD_BY_ID_LAST_FIELD prog_id | ||||||
| 
 | 
 | ||||||
| struct bpf_prog *bpf_prog_by_id(u32 id) | struct bpf_prog *bpf_prog_by_id(u32 id) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Alexei Starovoitov
						Alexei Starovoitov