xt_bpf.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /* Xtables module to match packets using a BPF filter.
  2. * Copyright 2013 Google Inc.
  3. * Written by Willem de Bruijn <willemb@google.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. */
  9. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  10. #include <linux/module.h>
  11. #include <linux/syscalls.h>
  12. #include <linux/skbuff.h>
  13. #include <linux/filter.h>
  14. #include <linux/bpf.h>
  15. #include <linux/netfilter/xt_bpf.h>
  16. #include <linux/netfilter/x_tables.h>
  17. MODULE_AUTHOR("Willem de Bruijn <willemb@google.com>");
  18. MODULE_DESCRIPTION("Xtables: BPF filter match");
  19. MODULE_LICENSE("GPL");
  20. MODULE_ALIAS("ipt_bpf");
  21. MODULE_ALIAS("ip6t_bpf");
  22. static int __bpf_mt_check_bytecode(struct sock_filter *insns, __u16 len,
  23. struct bpf_prog **ret)
  24. {
  25. struct sock_fprog_kern program;
  26. if (len > XT_BPF_MAX_NUM_INSTR)
  27. return -EINVAL;
  28. program.len = len;
  29. program.filter = insns;
  30. if (bpf_prog_create(ret, &program)) {
  31. pr_info_ratelimited("check failed: parse error\n");
  32. return -EINVAL;
  33. }
  34. return 0;
  35. }
  36. static int __bpf_mt_check_fd(int fd, struct bpf_prog **ret)
  37. {
  38. struct bpf_prog *prog;
  39. prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_SOCKET_FILTER);
  40. if (IS_ERR(prog))
  41. return PTR_ERR(prog);
  42. *ret = prog;
  43. return 0;
  44. }
  45. static int __bpf_mt_check_path(const char *path, struct bpf_prog **ret)
  46. {
  47. if (strnlen(path, XT_BPF_PATH_MAX) == XT_BPF_PATH_MAX)
  48. return -EINVAL;
  49. *ret = bpf_prog_get_type_path(path, BPF_PROG_TYPE_SOCKET_FILTER);
  50. return PTR_ERR_OR_ZERO(*ret);
  51. }
  52. static int bpf_mt_check(const struct xt_mtchk_param *par)
  53. {
  54. struct xt_bpf_info *info = par->matchinfo;
  55. return __bpf_mt_check_bytecode(info->bpf_program,
  56. info->bpf_program_num_elem,
  57. &info->filter);
  58. }
  59. static int bpf_mt_check_v1(const struct xt_mtchk_param *par)
  60. {
  61. struct xt_bpf_info_v1 *info = par->matchinfo;
  62. if (info->mode == XT_BPF_MODE_BYTECODE)
  63. return __bpf_mt_check_bytecode(info->bpf_program,
  64. info->bpf_program_num_elem,
  65. &info->filter);
  66. else if (info->mode == XT_BPF_MODE_FD_ELF)
  67. return __bpf_mt_check_fd(info->fd, &info->filter);
  68. else if (info->mode == XT_BPF_MODE_PATH_PINNED)
  69. return __bpf_mt_check_path(info->path, &info->filter);
  70. else
  71. return -EINVAL;
  72. }
  73. static bool bpf_mt(const struct sk_buff *skb, struct xt_action_param *par)
  74. {
  75. const struct xt_bpf_info *info = par->matchinfo;
  76. return BPF_PROG_RUN(info->filter, skb);
  77. }
  78. static bool bpf_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
  79. {
  80. const struct xt_bpf_info_v1 *info = par->matchinfo;
  81. return !!bpf_prog_run_save_cb(info->filter, (struct sk_buff *) skb);
  82. }
  83. static void bpf_mt_destroy(const struct xt_mtdtor_param *par)
  84. {
  85. const struct xt_bpf_info *info = par->matchinfo;
  86. bpf_prog_destroy(info->filter);
  87. }
  88. static void bpf_mt_destroy_v1(const struct xt_mtdtor_param *par)
  89. {
  90. const struct xt_bpf_info_v1 *info = par->matchinfo;
  91. bpf_prog_destroy(info->filter);
  92. }
  93. static struct xt_match bpf_mt_reg[] __read_mostly = {
  94. {
  95. .name = "bpf",
  96. .revision = 0,
  97. .family = NFPROTO_UNSPEC,
  98. .checkentry = bpf_mt_check,
  99. .match = bpf_mt,
  100. .destroy = bpf_mt_destroy,
  101. .matchsize = sizeof(struct xt_bpf_info),
  102. .usersize = offsetof(struct xt_bpf_info, filter),
  103. .me = THIS_MODULE,
  104. },
  105. {
  106. .name = "bpf",
  107. .revision = 1,
  108. .family = NFPROTO_UNSPEC,
  109. .checkentry = bpf_mt_check_v1,
  110. .match = bpf_mt_v1,
  111. .destroy = bpf_mt_destroy_v1,
  112. .matchsize = sizeof(struct xt_bpf_info_v1),
  113. .usersize = offsetof(struct xt_bpf_info_v1, filter),
  114. .me = THIS_MODULE,
  115. },
  116. };
  117. static int __init bpf_mt_init(void)
  118. {
  119. return xt_register_matches(bpf_mt_reg, ARRAY_SIZE(bpf_mt_reg));
  120. }
  121. static void __exit bpf_mt_exit(void)
  122. {
  123. xt_unregister_matches(bpf_mt_reg, ARRAY_SIZE(bpf_mt_reg));
  124. }
  125. module_init(bpf_mt_init);
  126. module_exit(bpf_mt_exit);