1 // SPDX-License-Identifier: GPL-2.0 2 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 3 #include <linux/init.h> 4 #include <linux/module.h> 5 #include <linux/pid.h> 6 #include <linux/fs.h> 7 #include <linux/sched/signal.h> 8 #include "bpf_preload.h" 9 10 extern char bpf_preload_umd_start; 11 extern char bpf_preload_umd_end; 12 13 static int preload(struct bpf_preload_info *obj); 14 static int finish(void); 15 16 static struct bpf_preload_ops umd_ops = { 17 .info.driver_name = "bpf_preload", 18 .preload = preload, 19 .finish = finish, 20 .owner = THIS_MODULE, 21 }; 22 23 static int preload(struct bpf_preload_info *obj) 24 { 25 int magic = BPF_PRELOAD_START; 26 loff_t pos = 0; 27 int i, err; 28 ssize_t n; 29 30 err = fork_usermode_driver(&umd_ops.info); 31 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; 47 } 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 tgid = umd_ops.info.tgid; 64 wait_event(tgid->wait_pidfd, thread_group_exited(tgid)); 65 umd_ops.info.tgid = NULL; 66 return 0; 67 } 68 69 static int __init load_umd(void) 70 { 71 int err; 72 73 err = umd_load_blob(&umd_ops.info, &bpf_preload_umd_start, 74 &bpf_preload_umd_end - &bpf_preload_umd_start); 75 if (err) 76 return err; 77 bpf_preload_ops = &umd_ops; 78 return err; 79 } 80 81 static void __exit fini_umd(void) 82 { 83 bpf_preload_ops = NULL; 84 /* kill UMD in case it's still there due to earlier error */ 85 kill_pid(umd_ops.info.tgid, SIGKILL, 1); 86 umd_ops.info.tgid = NULL; 87 umd_unload_blob(&umd_ops.info); 88 } 89 late_initcall(load_umd); 90 module_exit(fini_umd); 91 MODULE_LICENSE("GPL"); 92