linux/net/ipv6/netfilter/ip6table_security.c
<<
>>
Prefs
   1/*
   2 * "security" table for IPv6
   3 *
   4 * This is for use by Mandatory Access Control (MAC) security models,
   5 * which need to be able to manage security policy in separate context
   6 * to DAC.
   7 *
   8 * Based on iptable_mangle.c
   9 *
  10 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
  11 * Copyright (C) 2000-2004 Netfilter Core Team <coreteam <at> netfilter.org>
  12 * Copyright (C) 2008 Red Hat, Inc., James Morris <jmorris <at> redhat.com>
  13 *
  14 * This program is free software; you can redistribute it and/or modify
  15 * it under the terms of the GNU General Public License version 2 as
  16 * published by the Free Software Foundation.
  17 */
  18#include <linux/module.h>
  19#include <linux/netfilter_ipv6/ip6_tables.h>
  20
  21MODULE_LICENSE("GPL");
  22MODULE_AUTHOR("James Morris <jmorris <at> redhat.com>");
  23MODULE_DESCRIPTION("ip6tables security table, for MAC rules");
  24
  25#define SECURITY_VALID_HOOKS    (1 << NF_INET_LOCAL_IN) | \
  26                                (1 << NF_INET_FORWARD) | \
  27                                (1 << NF_INET_LOCAL_OUT)
  28
  29static struct
  30{
  31        struct ip6t_replace repl;
  32        struct ip6t_standard entries[3];
  33        struct ip6t_error term;
  34} initial_table __net_initdata = {
  35        .repl = {
  36                .name = "security",
  37                .valid_hooks = SECURITY_VALID_HOOKS,
  38                .num_entries = 4,
  39                .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
  40                .hook_entry = {
  41                        [NF_INET_LOCAL_IN]      = 0,
  42                        [NF_INET_FORWARD]       = sizeof(struct ip6t_standard),
  43                        [NF_INET_LOCAL_OUT]     = sizeof(struct ip6t_standard) * 2,
  44                },
  45                .underflow = {
  46                        [NF_INET_LOCAL_IN]      = 0,
  47                        [NF_INET_FORWARD]       = sizeof(struct ip6t_standard),
  48                        [NF_INET_LOCAL_OUT]     = sizeof(struct ip6t_standard) * 2,
  49                },
  50        },
  51        .entries = {
  52                IP6T_STANDARD_INIT(NF_ACCEPT),  /* LOCAL_IN */
  53                IP6T_STANDARD_INIT(NF_ACCEPT),  /* FORWARD */
  54                IP6T_STANDARD_INIT(NF_ACCEPT),  /* LOCAL_OUT */
  55        },
  56        .term = IP6T_ERROR_INIT,                /* ERROR */
  57};
  58
  59static struct xt_table security_table = {
  60        .name           = "security",
  61        .valid_hooks    = SECURITY_VALID_HOOKS,
  62        .lock           = __RW_LOCK_UNLOCKED(security_table.lock),
  63        .me             = THIS_MODULE,
  64        .af             = AF_INET6,
  65};
  66
  67static unsigned int
  68ip6t_local_in_hook(unsigned int hook,
  69                   struct sk_buff *skb,
  70                   const struct net_device *in,
  71                   const struct net_device *out,
  72                   int (*okfn)(struct sk_buff *))
  73{
  74        return ip6t_do_table(skb, hook, in, out,
  75                             nf_local_in_net(in, out)->ipv6.ip6table_security);
  76}
  77
  78static unsigned int
  79ip6t_forward_hook(unsigned int hook,
  80                  struct sk_buff *skb,
  81                  const struct net_device *in,
  82                  const struct net_device *out,
  83                  int (*okfn)(struct sk_buff *))
  84{
  85        return ip6t_do_table(skb, hook, in, out,
  86                             nf_forward_net(in, out)->ipv6.ip6table_security);
  87}
  88
  89static unsigned int
  90ip6t_local_out_hook(unsigned int hook,
  91                    struct sk_buff *skb,
  92                    const struct net_device *in,
  93                    const struct net_device *out,
  94                    int (*okfn)(struct sk_buff *))
  95{
  96        /* TBD: handle short packets via raw socket */
  97        return ip6t_do_table(skb, hook, in, out,
  98                             nf_local_out_net(in, out)->ipv6.ip6table_security);
  99}
 100
 101static struct nf_hook_ops ip6t_ops[] __read_mostly = {
 102        {
 103                .hook           = ip6t_local_in_hook,
 104                .owner          = THIS_MODULE,
 105                .pf             = PF_INET6,
 106                .hooknum        = NF_INET_LOCAL_IN,
 107                .priority       = NF_IP6_PRI_SECURITY,
 108        },
 109        {
 110                .hook           = ip6t_forward_hook,
 111                .owner          = THIS_MODULE,
 112                .pf             = PF_INET6,
 113                .hooknum        = NF_INET_FORWARD,
 114                .priority       = NF_IP6_PRI_SECURITY,
 115        },
 116        {
 117                .hook           = ip6t_local_out_hook,
 118                .owner          = THIS_MODULE,
 119                .pf             = PF_INET6,
 120                .hooknum        = NF_INET_LOCAL_OUT,
 121                .priority       = NF_IP6_PRI_SECURITY,
 122        },
 123};
 124
 125static int __net_init ip6table_security_net_init(struct net *net)
 126{
 127        net->ipv6.ip6table_security =
 128                ip6t_register_table(net, &security_table, &initial_table.repl);
 129
 130        if (IS_ERR(net->ipv6.ip6table_security))
 131                return PTR_ERR(net->ipv6.ip6table_security);
 132
 133        return 0;
 134}
 135
 136static void __net_exit ip6table_security_net_exit(struct net *net)
 137{
 138        ip6t_unregister_table(net->ipv6.ip6table_security);
 139}
 140
 141static struct pernet_operations ip6table_security_net_ops = {
 142        .init = ip6table_security_net_init,
 143        .exit = ip6table_security_net_exit,
 144};
 145
 146static int __init ip6table_security_init(void)
 147{
 148        int ret;
 149
 150        ret = register_pernet_subsys(&ip6table_security_net_ops);
 151        if (ret < 0)
 152                return ret;
 153
 154        ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
 155        if (ret < 0)
 156                goto cleanup_table;
 157
 158        return ret;
 159
 160cleanup_table:
 161        unregister_pernet_subsys(&ip6table_security_net_ops);
 162        return ret;
 163}
 164
 165static void __exit ip6table_security_fini(void)
 166{
 167        nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
 168        unregister_pernet_subsys(&ip6table_security_net_ops);
 169}
 170
 171module_init(ip6table_security_init);
 172module_exit(ip6table_security_fini);
 173