Skip to content

Commit a228a64

Browse files
author
Alexei Starovoitov
committed
bpf: Add bpf_prog iterator
It's mostly a copy paste of commit 6086d29 ("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 <[email protected]> Acked-by: Yonghong Song <[email protected]> Acked-by: Daniel Borkmann <[email protected]>
1 parent 3f9969f commit a228a64

File tree

4 files changed

+124
-1
lines changed

4 files changed

+124
-1
lines changed

include/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,7 @@ int generic_map_delete_batch(struct bpf_map *map,
11171117
const union bpf_attr *attr,
11181118
union bpf_attr __user *uattr);
11191119
struct bpf_map *bpf_map_get_curr_or_next(u32 *id);
1120+
struct bpf_prog *bpf_prog_get_curr_or_next(u32 *id);
11201121

11211122
extern int sysctl_unprivileged_bpf_disabled;
11221123

kernel/bpf/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
obj-y := core.o
33
CFLAGS_core.o += $(call cc-disable-warning, override-init)
44

5-
obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o bpf_iter.o map_iter.o task_iter.o
5+
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
66
obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o
77
obj-$(CONFIG_BPF_SYSCALL) += local_storage.o queue_stack_maps.o ringbuf.o
88
obj-$(CONFIG_BPF_SYSCALL) += disasm.o

kernel/bpf/prog_iter.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/* Copyright (c) 2020 Facebook */
3+
#include <linux/bpf.h>
4+
#include <linux/fs.h>
5+
#include <linux/filter.h>
6+
#include <linux/kernel.h>
7+
#include <linux/btf_ids.h>
8+
9+
struct bpf_iter_seq_prog_info {
10+
u32 prog_id;
11+
};
12+
13+
static void *bpf_prog_seq_start(struct seq_file *seq, loff_t *pos)
14+
{
15+
struct bpf_iter_seq_prog_info *info = seq->private;
16+
struct bpf_prog *prog;
17+
18+
prog = bpf_prog_get_curr_or_next(&info->prog_id);
19+
if (!prog)
20+
return NULL;
21+
22+
if (*pos == 0)
23+
++*pos;
24+
return prog;
25+
}
26+
27+
static void *bpf_prog_seq_next(struct seq_file *seq, void *v, loff_t *pos)
28+
{
29+
struct bpf_iter_seq_prog_info *info = seq->private;
30+
31+
++*pos;
32+
++info->prog_id;
33+
bpf_prog_put((struct bpf_prog *)v);
34+
return bpf_prog_get_curr_or_next(&info->prog_id);
35+
}
36+
37+
struct bpf_iter__bpf_prog {
38+
__bpf_md_ptr(struct bpf_iter_meta *, meta);
39+
__bpf_md_ptr(struct bpf_prog *, prog);
40+
};
41+
42+
DEFINE_BPF_ITER_FUNC(bpf_prog, struct bpf_iter_meta *meta, struct bpf_prog *prog)
43+
44+
static int __bpf_prog_seq_show(struct seq_file *seq, void *v, bool in_stop)
45+
{
46+
struct bpf_iter__bpf_prog ctx;
47+
struct bpf_iter_meta meta;
48+
struct bpf_prog *prog;
49+
int ret = 0;
50+
51+
ctx.meta = &meta;
52+
ctx.prog = v;
53+
meta.seq = seq;
54+
prog = bpf_iter_get_info(&meta, in_stop);
55+
if (prog)
56+
ret = bpf_iter_run_prog(prog, &ctx);
57+
58+
return ret;
59+
}
60+
61+
static int bpf_prog_seq_show(struct seq_file *seq, void *v)
62+
{
63+
return __bpf_prog_seq_show(seq, v, false);
64+
}
65+
66+
static void bpf_prog_seq_stop(struct seq_file *seq, void *v)
67+
{
68+
if (!v)
69+
(void)__bpf_prog_seq_show(seq, v, true);
70+
else
71+
bpf_prog_put((struct bpf_prog *)v);
72+
}
73+
74+
static const struct seq_operations bpf_prog_seq_ops = {
75+
.start = bpf_prog_seq_start,
76+
.next = bpf_prog_seq_next,
77+
.stop = bpf_prog_seq_stop,
78+
.show = bpf_prog_seq_show,
79+
};
80+
81+
BTF_ID_LIST(btf_bpf_prog_id)
82+
BTF_ID(struct, bpf_prog)
83+
84+
static struct bpf_iter_reg bpf_prog_reg_info = {
85+
.target = "bpf_prog",
86+
.seq_ops = &bpf_prog_seq_ops,
87+
.init_seq_private = NULL,
88+
.fini_seq_private = NULL,
89+
.seq_priv_size = sizeof(struct bpf_iter_seq_prog_info),
90+
.ctx_arg_info_size = 1,
91+
.ctx_arg_info = {
92+
{ offsetof(struct bpf_iter__bpf_prog, prog),
93+
PTR_TO_BTF_ID_OR_NULL },
94+
},
95+
};
96+
97+
static int __init bpf_prog_iter_init(void)
98+
{
99+
bpf_prog_reg_info.ctx_arg_info[0].btf_id = *btf_bpf_prog_id;
100+
return bpf_iter_reg_target(&bpf_prog_reg_info);
101+
}
102+
103+
late_initcall(bpf_prog_iter_init);

kernel/bpf/syscall.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3044,6 +3044,25 @@ struct bpf_map *bpf_map_get_curr_or_next(u32 *id)
30443044
return map;
30453045
}
30463046

3047+
struct bpf_prog *bpf_prog_get_curr_or_next(u32 *id)
3048+
{
3049+
struct bpf_prog *prog;
3050+
3051+
spin_lock_bh(&prog_idr_lock);
3052+
again:
3053+
prog = idr_get_next(&prog_idr, id);
3054+
if (prog) {
3055+
prog = bpf_prog_inc_not_zero(prog);
3056+
if (IS_ERR(prog)) {
3057+
(*id)++;
3058+
goto again;
3059+
}
3060+
}
3061+
spin_unlock_bh(&prog_idr_lock);
3062+
3063+
return prog;
3064+
}
3065+
30473066
#define BPF_PROG_GET_FD_BY_ID_LAST_FIELD prog_id
30483067

30493068
struct bpf_prog *bpf_prog_by_id(u32 id)

0 commit comments

Comments
 (0)