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