xt_SECMARK.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Module for modifying the secmark field of the skb, for use by
  4. * security subsystems.
  5. *
  6. * Based on the nfmark match by:
  7. * (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
  8. *
  9. * (C) 2006,2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
  10. */
  11. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  12. #include <linux/module.h>
  13. #include <linux/security.h>
  14. #include <linux/skbuff.h>
  15. #include <linux/netfilter/x_tables.h>
  16. #include <linux/netfilter/xt_SECMARK.h>
  17. MODULE_LICENSE("GPL");
  18. MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
  19. MODULE_DESCRIPTION("Xtables: packet security mark modification");
  20. MODULE_ALIAS("ipt_SECMARK");
  21. MODULE_ALIAS("ip6t_SECMARK");
  22. static u8 mode;
  23. static unsigned int
  24. secmark_tg(struct sk_buff *skb, const struct xt_secmark_target_info_v1 *info)
  25. {
  26. u32 secmark = 0;
  27. switch (mode) {
  28. case SECMARK_MODE_SEL:
  29. secmark = info->secid;
  30. break;
  31. default:
  32. BUG();
  33. }
  34. skb->secmark = secmark;
  35. return XT_CONTINUE;
  36. }
  37. static int checkentry_lsm(struct xt_secmark_target_info_v1 *info)
  38. {
  39. int err;
  40. info->secctx[SECMARK_SECCTX_MAX - 1] = '\0';
  41. info->secid = 0;
  42. err = security_secctx_to_secid(info->secctx, strlen(info->secctx),
  43. &info->secid);
  44. if (err) {
  45. if (err == -EINVAL)
  46. pr_info_ratelimited("invalid security context \'%s\'\n",
  47. info->secctx);
  48. return err;
  49. }
  50. if (!info->secid) {
  51. pr_info_ratelimited("unable to map security context \'%s\'\n",
  52. info->secctx);
  53. return -ENOENT;
  54. }
  55. err = security_secmark_relabel_packet(info->secid);
  56. if (err) {
  57. pr_info_ratelimited("unable to obtain relabeling permission\n");
  58. return err;
  59. }
  60. security_secmark_refcount_inc();
  61. return 0;
  62. }
  63. static int
  64. secmark_tg_check(const char *table, struct xt_secmark_target_info_v1 *info)
  65. {
  66. int err;
  67. if (strcmp(table, "mangle") != 0 &&
  68. strcmp(table, "security") != 0) {
  69. pr_info_ratelimited("only valid in \'mangle\' or \'security\' table, not \'%s\'\n",
  70. table);
  71. return -EINVAL;
  72. }
  73. if (mode && mode != info->mode) {
  74. pr_info_ratelimited("mode already set to %hu cannot mix with rules for mode %hu\n",
  75. mode, info->mode);
  76. return -EINVAL;
  77. }
  78. switch (info->mode) {
  79. case SECMARK_MODE_SEL:
  80. break;
  81. default:
  82. pr_info_ratelimited("invalid mode: %hu\n", info->mode);
  83. return -EINVAL;
  84. }
  85. err = checkentry_lsm(info);
  86. if (err)
  87. return err;
  88. if (!mode)
  89. mode = info->mode;
  90. return 0;
  91. }
  92. static void secmark_tg_destroy(const struct xt_tgdtor_param *par)
  93. {
  94. switch (mode) {
  95. case SECMARK_MODE_SEL:
  96. security_secmark_refcount_dec();
  97. }
  98. }
  99. static int secmark_tg_check_v0(const struct xt_tgchk_param *par)
  100. {
  101. struct xt_secmark_target_info *info = par->targinfo;
  102. struct xt_secmark_target_info_v1 newinfo = {
  103. .mode = info->mode,
  104. };
  105. int ret;
  106. memcpy(newinfo.secctx, info->secctx, SECMARK_SECCTX_MAX);
  107. ret = secmark_tg_check(par->table, &newinfo);
  108. info->secid = newinfo.secid;
  109. return ret;
  110. }
  111. static unsigned int
  112. secmark_tg_v0(struct sk_buff *skb, const struct xt_action_param *par)
  113. {
  114. const struct xt_secmark_target_info *info = par->targinfo;
  115. struct xt_secmark_target_info_v1 newinfo = {
  116. .secid = info->secid,
  117. };
  118. return secmark_tg(skb, &newinfo);
  119. }
  120. static int secmark_tg_check_v1(const struct xt_tgchk_param *par)
  121. {
  122. return secmark_tg_check(par->table, par->targinfo);
  123. }
  124. static unsigned int
  125. secmark_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
  126. {
  127. return secmark_tg(skb, par->targinfo);
  128. }
  129. static struct xt_target secmark_tg_reg[] __read_mostly = {
  130. {
  131. .name = "SECMARK",
  132. .revision = 0,
  133. .family = NFPROTO_UNSPEC,
  134. .checkentry = secmark_tg_check_v0,
  135. .destroy = secmark_tg_destroy,
  136. .target = secmark_tg_v0,
  137. .targetsize = sizeof(struct xt_secmark_target_info),
  138. .me = THIS_MODULE,
  139. },
  140. {
  141. .name = "SECMARK",
  142. .revision = 1,
  143. .family = NFPROTO_UNSPEC,
  144. .checkentry = secmark_tg_check_v1,
  145. .destroy = secmark_tg_destroy,
  146. .target = secmark_tg_v1,
  147. .targetsize = sizeof(struct xt_secmark_target_info_v1),
  148. .usersize = offsetof(struct xt_secmark_target_info_v1, secid),
  149. .me = THIS_MODULE,
  150. },
  151. };
  152. static int __init secmark_tg_init(void)
  153. {
  154. return xt_register_targets(secmark_tg_reg, ARRAY_SIZE(secmark_tg_reg));
  155. }
  156. static void __exit secmark_tg_exit(void)
  157. {
  158. xt_unregister_targets(secmark_tg_reg, ARRAY_SIZE(secmark_tg_reg));
  159. }
  160. module_init(secmark_tg_init);
  161. module_exit(secmark_tg_exit);