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("invalid security context \'%s\'\n", info->secctx);
  64                return err;
  65        }
  66
  67        if (!info->secid) {
  68                pr_info("unable to map security context \'%s\'\n", info->secctx);
  69                return -ENOENT;
  70        }
  71
  72        err = security_secmark_relabel_packet(info->secid);
  73        if (err) {
  74                pr_info("unable to obtain relabeling permission\n");
  75                return err;
  76        }
  77
  78        security_secmark_refcount_inc();
  79        return 0;
  80}
  81
  82static int secmark_tg_check(const struct xt_tgchk_param *par)
  83{
  84        struct xt_secmark_target_info *info = par->targinfo;
  85        int err;
  86
  87        if (strcmp(par->table, "mangle") != 0 &&
  88            strcmp(par->table, "security") != 0) {
  89                pr_info("target only valid in the \'mangle\' "
  90                        "or \'security\' tables, not \'%s\'.\n", par->table);
  91                return -EINVAL;
  92        }
  93
  94        if (mode && mode != info->mode) {
  95                pr_info("mode already set to %hu cannot mix with "
  96                        "rules for mode %hu\n", mode, info->mode);
  97                return -EINVAL;
  98        }
  99
 100        switch (info->mode) {
 101        case SECMARK_MODE_SEL:
 102                break;
 103        default:
 104                pr_info("invalid mode: %hu\n", info->mode);
 105                return -EINVAL;
 106        }
 107
 108        err = checkentry_lsm(info);
 109        if (err)
 110                return err;
 111
 112        if (!mode)
 113                mode = info->mode;
 114        return 0;
 115}
 116
 117static void secmark_tg_destroy(const struct xt_tgdtor_param *par)
 118{
 119        switch (mode) {
 120        case SECMARK_MODE_SEL:
 121                security_secmark_refcount_dec();
 122        }
 123}
 124
 125static struct xt_target secmark_tg_reg __read_mostly = {
 126        .name       = "SECMARK",
 127        .revision   = 0,
 128        .family     = NFPROTO_UNSPEC,
 129        .checkentry = secmark_tg_check,
 130        .destroy    = secmark_tg_destroy,
 131        .target     = secmark_tg,
 132        .targetsize = sizeof(struct xt_secmark_target_info),
 133        .me         = THIS_MODULE,
 134};
 135
 136static int __init secmark_tg_init(void)
 137{
 138        return xt_register_target(&secmark_tg_reg);
 139}
 140
 141static void __exit secmark_tg_exit(void)
 142{
 143        xt_unregister_target(&secmark_tg_reg);
 144}
 145
 146module_init(secmark_tg_init);
 147module_exit(secmark_tg_exit);
 148