Skip to content

Commit cb80ddc

Browse files
Alexei Starovoitovborkmann
authored andcommitted
bpf: Convert bpf_preload.ko to use light skeleton.
The main change is a move of the single line #include "iterators.lskel.h" from iterators/iterators.c to bpf_preload_kern.c. Which means that generated light skeleton can be used from user space or user mode driver like iterators.c or from the kernel module or the kernel itself. The direct use of light skeleton from the kernel module simplifies the code, since UMD is no longer necessary. The libbpf.a required user space and UMD. The CO-RE in the kernel and generated "loader bpf program" used by the light skeleton are capable to perform complex loading operations traditionally provided by libbpf. In addition UMD approach was launching UMD process every time bpffs has to be mounted. With light skeleton in the kernel the bpf_preload kernel module loads bpf iterators once and pins them multiple times into different bpffs mounts. Signed-off-by: Alexei Starovoitov <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Yonghong Song <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent d7beb3d commit cb80ddc

File tree

9 files changed

+70
-247
lines changed

9 files changed

+70
-247
lines changed

kernel/bpf/inode.c

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -710,52 +710,33 @@ static DEFINE_MUTEX(bpf_preload_lock);
710710
static int populate_bpffs(struct dentry *parent)
711711
{
712712
struct bpf_preload_info objs[BPF_PRELOAD_LINKS] = {};
713-
struct bpf_link *links[BPF_PRELOAD_LINKS] = {};
714713
int err = 0, i;
715714

716715
/* grab the mutex to make sure the kernel interactions with bpf_preload
717-
* UMD are serialized
716+
* are serialized
718717
*/
719718
mutex_lock(&bpf_preload_lock);
720719

721720
/* if bpf_preload.ko wasn't built into vmlinux then load it */
722721
if (!bpf_preload_mod_get())
723722
goto out;
724723

725-
if (!bpf_preload_ops->info.tgid) {
726-
/* preload() will start UMD that will load BPF iterator programs */
727-
err = bpf_preload_ops->preload(objs);
728-
if (err)
724+
err = bpf_preload_ops->preload(objs);
725+
if (err)
726+
goto out_put;
727+
for (i = 0; i < BPF_PRELOAD_LINKS; i++) {
728+
bpf_link_inc(objs[i].link);
729+
err = bpf_iter_link_pin_kernel(parent,
730+
objs[i].link_name, objs[i].link);
731+
if (err) {
732+
bpf_link_put(objs[i].link);
729733
goto out_put;
730-
for (i = 0; i < BPF_PRELOAD_LINKS; i++) {
731-
links[i] = bpf_link_by_id(objs[i].link_id);
732-
if (IS_ERR(links[i])) {
733-
err = PTR_ERR(links[i]);
734-
goto out_put;
735-
}
736734
}
737-
for (i = 0; i < BPF_PRELOAD_LINKS; i++) {
738-
err = bpf_iter_link_pin_kernel(parent,
739-
objs[i].link_name, links[i]);
740-
if (err)
741-
goto out_put;
742-
/* do not unlink successfully pinned links even
743-
* if later link fails to pin
744-
*/
745-
links[i] = NULL;
746-
}
747-
/* finish() will tell UMD process to exit */
748-
err = bpf_preload_ops->finish();
749-
if (err)
750-
goto out_put;
751735
}
752736
out_put:
753737
bpf_preload_mod_put();
754738
out:
755739
mutex_unlock(&bpf_preload_lock);
756-
for (i = 0; i < BPF_PRELOAD_LINKS && err; i++)
757-
if (!IS_ERR_OR_NULL(links[i]))
758-
bpf_link_put(links[i]);
759740
return err;
760741
}
761742

kernel/bpf/preload/Kconfig

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ menuconfig BPF_PRELOAD
1818

1919
if BPF_PRELOAD
2020
config BPF_PRELOAD_UMD
21-
tristate "bpf_preload kernel module with user mode driver"
22-
depends on CC_CAN_LINK
23-
depends on m || CC_CAN_LINK_STATIC
21+
tristate "bpf_preload kernel module"
2422
default m
2523
help
26-
This builds bpf_preload kernel module with embedded user mode driver.
24+
This builds bpf_preload kernel module with embedded BPF programs for
25+
introspection in bpffs.
2726
endif

kernel/bpf/preload/Makefile

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,6 @@
33
LIBBPF_SRCS = $(srctree)/tools/lib/bpf/
44
LIBBPF_INCLUDE = $(LIBBPF_SRCS)/..
55

6-
userccflags += -I $(srctree)/tools/include/ -I $(srctree)/tools/include/uapi \
7-
-I $(LIBBPF_INCLUDE) -Wno-unused-result
8-
9-
userprogs := bpf_preload_umd
10-
11-
bpf_preload_umd-objs := iterators/iterators.o
12-
13-
$(obj)/bpf_preload_umd:
14-
15-
$(obj)/bpf_preload_umd_blob.o: $(obj)/bpf_preload_umd
16-
176
obj-$(CONFIG_BPF_PRELOAD_UMD) += bpf_preload.o
18-
bpf_preload-objs += bpf_preload_kern.o bpf_preload_umd_blob.o
7+
CFLAGS_bpf_preload_kern.o += -I $(LIBBPF_INCLUDE)
8+
bpf_preload-objs += bpf_preload_kern.o

kernel/bpf/preload/bpf_preload.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
#ifndef _BPF_PRELOAD_H
33
#define _BPF_PRELOAD_H
44

5-
#include <linux/usermode_driver.h>
6-
#include "iterators/bpf_preload_common.h"
5+
struct bpf_preload_info {
6+
char link_name[16];
7+
struct bpf_link *link;
8+
};
79

810
struct bpf_preload_ops {
9-
struct umd_info info;
1011
int (*preload)(struct bpf_preload_info *);
11-
int (*finish)(void);
1212
struct module *owner;
1313
};
1414
extern struct bpf_preload_ops *bpf_preload_ops;

kernel/bpf/preload/bpf_preload_kern.c

Lines changed: 49 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -2,101 +2,80 @@
22
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
33
#include <linux/init.h>
44
#include <linux/module.h>
5-
#include <linux/pid.h>
6-
#include <linux/fs.h>
7-
#include <linux/sched/signal.h>
85
#include "bpf_preload.h"
6+
#include "iterators/iterators.lskel.h"
97

10-
extern char bpf_preload_umd_start;
11-
extern char bpf_preload_umd_end;
8+
static struct bpf_link *maps_link, *progs_link;
9+
static struct iterators_bpf *skel;
1210

13-
static int preload(struct bpf_preload_info *obj);
14-
static int finish(void);
11+
static void free_links_and_skel(void)
12+
{
13+
if (!IS_ERR_OR_NULL(maps_link))
14+
bpf_link_put(maps_link);
15+
if (!IS_ERR_OR_NULL(progs_link))
16+
bpf_link_put(progs_link);
17+
iterators_bpf__destroy(skel);
18+
}
19+
20+
static int preload(struct bpf_preload_info *obj)
21+
{
22+
strlcpy(obj[0].link_name, "maps.debug", sizeof(obj[0].link_name));
23+
obj[0].link = maps_link;
24+
strlcpy(obj[1].link_name, "progs.debug", sizeof(obj[1].link_name));
25+
obj[1].link = progs_link;
26+
return 0;
27+
}
1528

16-
static struct bpf_preload_ops umd_ops = {
17-
.info.driver_name = "bpf_preload",
29+
static struct bpf_preload_ops ops = {
1830
.preload = preload,
19-
.finish = finish,
2031
.owner = THIS_MODULE,
2132
};
2233

23-
static int preload(struct bpf_preload_info *obj)
34+
static int load_skel(void)
2435
{
25-
int magic = BPF_PRELOAD_START;
26-
loff_t pos = 0;
27-
int i, err;
28-
ssize_t n;
36+
int err;
2937

30-
err = fork_usermode_driver(&umd_ops.info);
38+
skel = iterators_bpf__open();
39+
if (!skel)
40+
return -ENOMEM;
41+
err = iterators_bpf__load(skel);
3142
if (err)
32-
return err;
33-
34-
/* send the start magic to let UMD proceed with loading BPF progs */
35-
n = kernel_write(umd_ops.info.pipe_to_umh,
36-
&magic, sizeof(magic), &pos);
37-
if (n != sizeof(magic))
38-
return -EPIPE;
39-
40-
/* receive bpf_link IDs and names from UMD */
41-
pos = 0;
42-
for (i = 0; i < BPF_PRELOAD_LINKS; i++) {
43-
n = kernel_read(umd_ops.info.pipe_from_umh,
44-
&obj[i], sizeof(*obj), &pos);
45-
if (n != sizeof(*obj))
46-
return -EPIPE;
43+
goto out;
44+
err = iterators_bpf__attach(skel);
45+
if (err)
46+
goto out;
47+
maps_link = bpf_link_get_from_fd(skel->links.dump_bpf_map_fd);
48+
if (IS_ERR(maps_link)) {
49+
err = PTR_ERR(maps_link);
50+
goto out;
4751
}
48-
return 0;
49-
}
50-
51-
static int finish(void)
52-
{
53-
int magic = BPF_PRELOAD_END;
54-
struct pid *tgid;
55-
loff_t pos = 0;
56-
ssize_t n;
57-
58-
/* send the last magic to UMD. It will do a normal exit. */
59-
n = kernel_write(umd_ops.info.pipe_to_umh,
60-
&magic, sizeof(magic), &pos);
61-
if (n != sizeof(magic))
62-
return -EPIPE;
63-
64-
tgid = umd_ops.info.tgid;
65-
if (tgid) {
66-
wait_event(tgid->wait_pidfd, thread_group_exited(tgid));
67-
umd_cleanup_helper(&umd_ops.info);
52+
progs_link = bpf_link_get_from_fd(skel->links.dump_bpf_prog_fd);
53+
if (IS_ERR(progs_link)) {
54+
err = PTR_ERR(progs_link);
55+
goto out;
6856
}
6957
return 0;
58+
out:
59+
free_links_and_skel();
60+
return err;
7061
}
7162

72-
static int __init load_umd(void)
63+
static int __init load(void)
7364
{
7465
int err;
7566

76-
err = umd_load_blob(&umd_ops.info, &bpf_preload_umd_start,
77-
&bpf_preload_umd_end - &bpf_preload_umd_start);
67+
err = load_skel();
7868
if (err)
7969
return err;
80-
bpf_preload_ops = &umd_ops;
70+
bpf_preload_ops = &ops;
8171
return err;
8272
}
8373

84-
static void __exit fini_umd(void)
74+
static void __exit fini(void)
8575
{
86-
struct pid *tgid;
87-
8876
bpf_preload_ops = NULL;
89-
90-
/* kill UMD in case it's still there due to earlier error */
91-
tgid = umd_ops.info.tgid;
92-
if (tgid) {
93-
kill_pid(tgid, SIGKILL, 1);
94-
95-
wait_event(tgid->wait_pidfd, thread_group_exited(tgid));
96-
umd_cleanup_helper(&umd_ops.info);
97-
}
98-
umd_unload_blob(&umd_ops.info);
77+
free_links_and_skel();
9978
}
100-
late_initcall(load_umd);
101-
module_exit(fini_umd);
79+
late_initcall(load);
80+
module_exit(fini);
10281
MODULE_LICENSE("GPL");

kernel/bpf/preload/bpf_preload_umd_blob.S

Lines changed: 0 additions & 7 deletions
This file was deleted.

kernel/bpf/preload/iterators/bpf_preload_common.h

Lines changed: 0 additions & 13 deletions
This file was deleted.

kernel/bpf/preload/iterators/iterators.c

Lines changed: 0 additions & 108 deletions
This file was deleted.

0 commit comments

Comments
 (0)