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