mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
2.2 KiB
102 lines
2.2 KiB
// SPDX-License-Identifier: GPL-2.0 |
|
#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" |
|
|
|
extern char bpf_preload_umd_start; |
|
extern char bpf_preload_umd_end; |
|
|
|
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 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; |
|
} |
|
return 0; |
|
} |
|
|
|
static int finish(void) |
|
{ |
|
int magic = BPF_PRELOAD_END; |
|
struct pid *tgid; |
|
loff_t pos = 0; |
|
ssize_t n; |
|
|
|
/* 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) |
|
{ |
|
int err; |
|
|
|
err = umd_load_blob(&umd_ops.info, &bpf_preload_umd_start, |
|
&bpf_preload_umd_end - &bpf_preload_umd_start); |
|
if (err) |
|
return err; |
|
bpf_preload_ops = &umd_ops; |
|
return err; |
|
} |
|
|
|
static void __exit fini_umd(void) |
|
{ |
|
struct pid *tgid; |
|
|
|
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); |
|
} |
|
late_initcall(load_umd); |
|
module_exit(fini_umd); |
|
MODULE_LICENSE("GPL");
|
|
|