mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
synced 2026-04-18 19:43:43 -04:00
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 <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Yonghong Song <yhs@fb.com> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20220209232001.27490-6-alexei.starovoitov@gmail.com
This commit is contained in:
committed by
Daniel Borkmann
parent
d7beb3d6ab
commit
cb80ddc671
@@ -2,101 +2,80 @@
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pid.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include "bpf_preload.h"
|
||||
#include "iterators/iterators.lskel.h"
|
||||
|
||||
extern char bpf_preload_umd_start;
|
||||
extern char bpf_preload_umd_end;
|
||||
static struct bpf_link *maps_link, *progs_link;
|
||||
static struct iterators_bpf *skel;
|
||||
|
||||
static int preload(struct bpf_preload_info *obj);
|
||||
static int finish(void);
|
||||
|
||||
static struct bpf_preload_ops umd_ops = {
|
||||
.info.driver_name = "bpf_preload",
|
||||
.preload = preload,
|
||||
.finish = finish,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
static void free_links_and_skel(void)
|
||||
{
|
||||
if (!IS_ERR_OR_NULL(maps_link))
|
||||
bpf_link_put(maps_link);
|
||||
if (!IS_ERR_OR_NULL(progs_link))
|
||||
bpf_link_put(progs_link);
|
||||
iterators_bpf__destroy(skel);
|
||||
}
|
||||
|
||||
static int preload(struct bpf_preload_info *obj)
|
||||
{
|
||||
int magic = BPF_PRELOAD_START;
|
||||
loff_t pos = 0;
|
||||
int i, err;
|
||||
ssize_t n;
|
||||
|
||||
err = fork_usermode_driver(&umd_ops.info);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* send the start magic to let UMD proceed with loading BPF progs */
|
||||
n = kernel_write(umd_ops.info.pipe_to_umh,
|
||||
&magic, sizeof(magic), &pos);
|
||||
if (n != sizeof(magic))
|
||||
return -EPIPE;
|
||||
|
||||
/* receive bpf_link IDs and names from UMD */
|
||||
pos = 0;
|
||||
for (i = 0; i < BPF_PRELOAD_LINKS; i++) {
|
||||
n = kernel_read(umd_ops.info.pipe_from_umh,
|
||||
&obj[i], sizeof(*obj), &pos);
|
||||
if (n != sizeof(*obj))
|
||||
return -EPIPE;
|
||||
}
|
||||
strlcpy(obj[0].link_name, "maps.debug", sizeof(obj[0].link_name));
|
||||
obj[0].link = maps_link;
|
||||
strlcpy(obj[1].link_name, "progs.debug", sizeof(obj[1].link_name));
|
||||
obj[1].link = progs_link;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int finish(void)
|
||||
{
|
||||
int magic = BPF_PRELOAD_END;
|
||||
struct pid *tgid;
|
||||
loff_t pos = 0;
|
||||
ssize_t n;
|
||||
static struct bpf_preload_ops ops = {
|
||||
.preload = preload,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
/* send the last magic to UMD. It will do a normal exit. */
|
||||
n = kernel_write(umd_ops.info.pipe_to_umh,
|
||||
&magic, sizeof(magic), &pos);
|
||||
if (n != sizeof(magic))
|
||||
return -EPIPE;
|
||||
|
||||
tgid = umd_ops.info.tgid;
|
||||
if (tgid) {
|
||||
wait_event(tgid->wait_pidfd, thread_group_exited(tgid));
|
||||
umd_cleanup_helper(&umd_ops.info);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init load_umd(void)
|
||||
static int load_skel(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = umd_load_blob(&umd_ops.info, &bpf_preload_umd_start,
|
||||
&bpf_preload_umd_end - &bpf_preload_umd_start);
|
||||
skel = iterators_bpf__open();
|
||||
if (!skel)
|
||||
return -ENOMEM;
|
||||
err = iterators_bpf__load(skel);
|
||||
if (err)
|
||||
return err;
|
||||
bpf_preload_ops = &umd_ops;
|
||||
goto out;
|
||||
err = iterators_bpf__attach(skel);
|
||||
if (err)
|
||||
goto out;
|
||||
maps_link = bpf_link_get_from_fd(skel->links.dump_bpf_map_fd);
|
||||
if (IS_ERR(maps_link)) {
|
||||
err = PTR_ERR(maps_link);
|
||||
goto out;
|
||||
}
|
||||
progs_link = bpf_link_get_from_fd(skel->links.dump_bpf_prog_fd);
|
||||
if (IS_ERR(progs_link)) {
|
||||
err = PTR_ERR(progs_link);
|
||||
goto out;
|
||||
}
|
||||
return 0;
|
||||
out:
|
||||
free_links_and_skel();
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit fini_umd(void)
|
||||
static int __init load(void)
|
||||
{
|
||||
struct pid *tgid;
|
||||
int err;
|
||||
|
||||
bpf_preload_ops = NULL;
|
||||
|
||||
/* kill UMD in case it's still there due to earlier error */
|
||||
tgid = umd_ops.info.tgid;
|
||||
if (tgid) {
|
||||
kill_pid(tgid, SIGKILL, 1);
|
||||
|
||||
wait_event(tgid->wait_pidfd, thread_group_exited(tgid));
|
||||
umd_cleanup_helper(&umd_ops.info);
|
||||
}
|
||||
umd_unload_blob(&umd_ops.info);
|
||||
err = load_skel();
|
||||
if (err)
|
||||
return err;
|
||||
bpf_preload_ops = &ops;
|
||||
return err;
|
||||
}
|
||||
late_initcall(load_umd);
|
||||
module_exit(fini_umd);
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
bpf_preload_ops = NULL;
|
||||
free_links_and_skel();
|
||||
}
|
||||
late_initcall(load);
|
||||
module_exit(fini);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
Reference in New Issue
Block a user