Skip to content

Commit

Permalink
netfilter: nf_tables: complete net namespace support
Browse files Browse the repository at this point in the history
Register family per netnamespace to ensure that sets are
only visible in its approapriate namespace.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  • Loading branch information
Pablo Neira Ayuso committed Oct 14, 2013
1 parent eb31628 commit 99633ab
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 35 deletions.
4 changes: 4 additions & 0 deletions include/net/net_namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
#include <net/netns/conntrack.h>
#endif
#include <net/netns/nftables.h>
#include <net/netns/xfrm.h>

struct user_namespace;
Expand Down Expand Up @@ -101,6 +102,9 @@ struct net {
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
struct netns_ct ct;
#endif
#if defined(CONFIG_NF_TABLES) || defined(CONFIG_NF_TABLES_MODULE)
struct netns_nftables nft;
#endif
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
struct netns_nf_frag nf_frag;
#endif
Expand Down
4 changes: 3 additions & 1 deletion include/net/netfilter/nf_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ static inline void nft_data_debug(const struct nft_data *data)
/**
* struct nft_ctx - nf_tables rule/set context
*
* @net: net namespace
* @skb: netlink skb
* @nlh: netlink message header
* @afi: address family info
Expand All @@ -76,6 +77,7 @@ static inline void nft_data_debug(const struct nft_data *data)
* @nla: netlink attributes
*/
struct nft_ctx {
struct net *net;
const struct sk_buff *skb;
const struct nlmsghdr *nlh;
const struct nft_af_info *afi;
Expand Down Expand Up @@ -462,7 +464,7 @@ struct nft_af_info {
nf_hookfn *hooks[NF_MAX_HOOKS];
};

extern int nft_register_afinfo(struct nft_af_info *);
extern int nft_register_afinfo(struct net *, struct nft_af_info *);
extern void nft_unregister_afinfo(struct nft_af_info *);

struct nf_chain_type {
Expand Down
15 changes: 15 additions & 0 deletions include/net/netns/nftables.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef _NETNS_NFTABLES_H_
#define _NETNS_NFTABLES_H_

#include <linux/list.h>

struct nft_af_info;

struct netns_nftables {
struct list_head af_info;
struct nft_af_info *ipv4;
struct nft_af_info *ipv6;
struct nft_af_info *bridge;
};

#endif
32 changes: 30 additions & 2 deletions net/bridge/netfilter/nf_tables_bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,42 @@ static struct nft_af_info nft_af_bridge __read_mostly = {
.owner = THIS_MODULE,
};

static int nf_tables_bridge_init_net(struct net *net)
{
net->nft.bridge = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
if (net->nft.bridge == NULL)
return -ENOMEM;

memcpy(net->nft.bridge, &nft_af_bridge, sizeof(nft_af_bridge));

if (nft_register_afinfo(net, net->nft.bridge) < 0)
goto err;

return 0;
err:
kfree(net->nft.bridge);
return -ENOMEM;
}

static void nf_tables_bridge_exit_net(struct net *net)
{
nft_unregister_afinfo(net->nft.bridge);
kfree(net->nft.bridge);
}

static struct pernet_operations nf_tables_bridge_net_ops = {
.init = nf_tables_bridge_init_net,
.exit = nf_tables_bridge_exit_net,
};

static int __init nf_tables_bridge_init(void)
{
return nft_register_afinfo(&nft_af_bridge);
return register_pernet_subsys(&nf_tables_bridge_net_ops);
}

static void __exit nf_tables_bridge_exit(void)
{
nft_unregister_afinfo(&nft_af_bridge);
return unregister_pernet_subsys(&nf_tables_bridge_net_ops);
}

module_init(nf_tables_bridge_init);
Expand Down
32 changes: 30 additions & 2 deletions net/ipv4/netfilter/nf_tables_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/ip.h>
#include <linux/netfilter_ipv4.h>
#include <net/netfilter/nf_tables.h>
#include <net/net_namespace.h>
#include <net/ip.h>
#include <net/net_namespace.h>
#include <net/netfilter/nf_tables_ipv4.h>
Expand Down Expand Up @@ -47,6 +48,33 @@ static struct nft_af_info nft_af_ipv4 __read_mostly = {
},
};

static int nf_tables_ipv4_init_net(struct net *net)
{
net->nft.ipv4 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
if (net->nft.ipv4 == NULL)
return -ENOMEM;

memcpy(net->nft.ipv4, &nft_af_ipv4, sizeof(nft_af_ipv4));

if (nft_register_afinfo(net, net->nft.ipv4) < 0)
goto err;

return 0;
err:
kfree(net->nft.ipv4);
return -ENOMEM;
}

static void nf_tables_ipv4_exit_net(struct net *net)
{
nft_unregister_afinfo(net->nft.ipv4);
kfree(net->nft.ipv4);
}

static struct pernet_operations nf_tables_ipv4_net_ops = {
.init = nf_tables_ipv4_init_net,
.exit = nf_tables_ipv4_exit_net,
};

static unsigned int
nft_do_chain_ipv4(const struct nf_hook_ops *ops,
Expand Down Expand Up @@ -83,12 +111,12 @@ static struct nf_chain_type filter_ipv4 = {
static int __init nf_tables_ipv4_init(void)
{
nft_register_chain_type(&filter_ipv4);
return nft_register_afinfo(&nft_af_ipv4);
return register_pernet_subsys(&nf_tables_ipv4_net_ops);
}

static void __exit nf_tables_ipv4_exit(void)
{
nft_unregister_afinfo(&nft_af_ipv4);
unregister_pernet_subsys(&nf_tables_ipv4_net_ops);
nft_unregister_chain_type(&filter_ipv4);
}

Expand Down
33 changes: 31 additions & 2 deletions net/ipv6/netfilter/nf_tables_ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,34 @@ static struct nft_af_info nft_af_ipv6 __read_mostly = {
},
};

static int nf_tables_ipv6_init_net(struct net *net)
{
net->nft.ipv6 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
if (net->nft.ipv6 == NULL)
return -ENOMEM;

memcpy(net->nft.ipv6, &nft_af_ipv6, sizeof(nft_af_ipv6));

if (nft_register_afinfo(net, net->nft.ipv6) < 0)
goto err;

return 0;
err:
kfree(net->nft.ipv6);
return -ENOMEM;
}

static void nf_tables_ipv6_exit_net(struct net *net)
{
nft_unregister_afinfo(net->nft.ipv6);
kfree(net->nft.ipv6);
}

static struct pernet_operations nf_tables_ipv6_net_ops = {
.init = nf_tables_ipv6_init_net,
.exit = nf_tables_ipv6_exit_net,
};

static unsigned int
nft_do_chain_ipv6(const struct nf_hook_ops *ops,
struct sk_buff *skb,
Expand Down Expand Up @@ -82,11 +110,12 @@ static struct nf_chain_type filter_ipv6 = {
static int __init nf_tables_ipv6_init(void)
{
nft_register_chain_type(&filter_ipv6);
return nft_register_afinfo(&nft_af_ipv6);
return register_pernet_subsys(&nf_tables_ipv6_net_ops);
}

static void __exit nf_tables_ipv6_exit(void)
{
nft_unregister_afinfo(&nft_af_ipv6);
unregister_pernet_subsys(&nf_tables_ipv6_net_ops);
nft_unregister_chain_type(&filter_ipv6);
}

Expand Down
Loading

0 comments on commit 99633ab

Please sign in to comment.