linux/net/netfilter/xt_SECMARK.c
<<
>>
Prefs
   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
  18MODULE_LICENSE("GPL");
  19MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
  20MODULE_DESCRIPTION("Xtables: packet security mark modification");
  21MODULE_ALIAS("ipt_SECMARK");
  22MODULE_ALIAS("ip6t_SECMARK");
  23
  24#define PFX "SECMARK: "
  25
  26static u8 mode;
  27
  28static unsigned int
  29secmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
  30{
  31        u32 secmark = 0;
  32        const struct xt_secmark_target_info *info = par->targinfo;
  33
  34        switch (mode) {
  35        case SECMARK_MODE_SEL:
  36                secmark = info->secid;
  37                break;
  38        default:
  39                BUG();
  40        }
  41
  42        skb->secmark = secmark;
  43        return XT_CONTINUE;
  44}
  45
  46static int checkentry_lsm(struct xt_secmark_target_info *info)
  47{
  48        int err;
  49
  50        info->secctx[SECMARK_SECCTX_MAX - 1] = '\0';
  51        info->secid = 0;
  52
  53        err = security_secctx_to_secid(info->secctx, strlen(info->secctx),
  54                                       &info->secid);
  55        if (err) {
  56                if (err == -EINVAL)
  57                        pr_info_ratelimited("invalid security context \'%s\'\n",
  58                                            info->secctx);
  59                return err;
  60        }
  61
  62        if (!info->secid) {
  63                pr_info_ratelimited("unable to map security context \'%s\'\n",
  64                                    info->secctx);
  65                return -ENOENT;
  66        }
  67
  68        err = security_secmark_relabel_packet(info->secid);
  69        if (err) {
  70                pr_info_ratelimited("unable to obtain relabeling permission\n");
  71                return err;
  72        }
  73
  74        security_secmark_refcount_inc();
  75        return 0;
  76}
  77
  78static int secmark_tg_check(const struct xt_tgchk_param *par)
  79{
  80        struct xt_secmark_target_info *info = par->targinfo;
  81        int err;
  82
  83        if (strcmp(par->table, "mangle") != 0 &&
  84            strcmp(par->table, "security") != 0) {
  85                pr_info_ratelimited("only valid in \'mangle\' or \'security\' table, not \'%s\'\n",
  86                                    par->table);
  87                return -EINVAL;
  88        }
  89
  90        if (mode && mode != info->mode) {
  91                pr_info_ratelimited("mode already set to %hu cannot mix with rules for mode %hu\n",
  92                                    mode, info->mode);
  93                return -EINVAL;
  94        }
  95
  96        switch (info->mode) {
  97        case SECMARK_MODE_SEL:
  98                break;
  99        default:
 100                pr_info_ratelimited("invalid mode: %hu\n", info->mode);
 101                return -EINVAL;
 102        }
 103
 104        err = checkentry_lsm(info);
 105        if (err)
 106                return err;
 107
 108        if (!mode)
 109                mode = info->mode;
 110        return 0;
 111}
 112
 113static void secmark_tg_destroy(const struct xt_tgdtor_param *par)
 114{
 115        switch (mode) {
 116        case SECMARK_MODE_SEL:
 117                security_secmark_refcount_dec();
 118        }
 119}
 120
 121static struct xt_target secmark_tg_reg __read_mostly = {
 122        .name       = "SECMARK",
 123        .revision   = 0,
 124        .family     = NFPROTO_UNSPEC,
 125        .checkentry = secmark_tg_check,
 126        .destroy    = secmark_tg_destroy,
 127        .target     = secmark_tg,
 128        .targetsize = sizeof(struct xt_secmark_target_info),
 129        .me         = THIS_MODULE,
 130};
 131
 132static int __init secmark_tg_init(void)
 133{
 134        return xt_register_target(&secmark_tg_reg);
 135}
 136
 137static void __exit secmark_tg_exit(void)
 138{
 139        xt_unregister_target(&secmark_tg_reg);
 140}
 141
 142module_init(secmark_tg_init);
 143module_exit(secmark_tg_exit);
 144