bpf_preload_kern.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. extern char bpf_preload_umd_start;
  10. extern char bpf_preload_umd_end;
  11. static int preload(struct bpf_preload_info *obj);
  12. static int finish(void);
  13. static struct bpf_preload_ops umd_ops = {
  14. .info.driver_name = "bpf_preload",
  15. .preload = preload,
  16. .finish = finish,
  17. .owner = THIS_MODULE,
  18. };
  19. static int preload(struct bpf_preload_info *obj)
  20. {
  21. int magic = BPF_PRELOAD_START;
  22. loff_t pos = 0;
  23. int i, err;
  24. ssize_t n;
  25. err = fork_usermode_driver(&umd_ops.info);
  26. if (err)
  27. return err;
  28. /* send the start magic to let UMD proceed with loading BPF progs */
  29. n = kernel_write(umd_ops.info.pipe_to_umh,
  30. &magic, sizeof(magic), &pos);
  31. if (n != sizeof(magic))
  32. return -EPIPE;
  33. /* receive bpf_link IDs and names from UMD */
  34. pos = 0;
  35. for (i = 0; i < BPF_PRELOAD_LINKS; i++) {
  36. n = kernel_read(umd_ops.info.pipe_from_umh,
  37. &obj[i], sizeof(*obj), &pos);
  38. if (n != sizeof(*obj))
  39. return -EPIPE;
  40. }
  41. return 0;
  42. }
  43. static int finish(void)
  44. {
  45. int magic = BPF_PRELOAD_END;
  46. struct pid *tgid;
  47. loff_t pos = 0;
  48. ssize_t n;
  49. /* send the last magic to UMD. It will do a normal exit. */
  50. n = kernel_write(umd_ops.info.pipe_to_umh,
  51. &magic, sizeof(magic), &pos);
  52. if (n != sizeof(magic))
  53. return -EPIPE;
  54. tgid = umd_ops.info.tgid;
  55. if (tgid) {
  56. wait_event(tgid->wait_pidfd, thread_group_exited(tgid));
  57. umd_cleanup_helper(&umd_ops.info);
  58. }
  59. return 0;
  60. }
  61. static int __init load_umd(void)
  62. {
  63. int err;
  64. err = umd_load_blob(&umd_ops.info, &bpf_preload_umd_start,
  65. &bpf_preload_umd_end - &bpf_preload_umd_start);
  66. if (err)
  67. return err;
  68. bpf_preload_ops = &umd_ops;
  69. return err;
  70. }
  71. static void __exit fini_umd(void)
  72. {
  73. struct pid *tgid;
  74. bpf_preload_ops = NULL;
  75. /* kill UMD in case it's still there due to earlier error */
  76. tgid = umd_ops.info.tgid;
  77. if (tgid) {
  78. kill_pid(tgid, SIGKILL, 1);
  79. wait_event(tgid->wait_pidfd, thread_group_exited(tgid));
  80. umd_cleanup_helper(&umd_ops.info);
  81. }
  82. umd_unload_blob(&umd_ops.info);
  83. }
  84. late_initcall(load_umd);
  85. module_exit(fini_umd);
  86. MODULE_LICENSE("GPL");