aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2013-10-10 17:28:33 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2013-10-14 12:00:59 -0400
commit99633ab29b2131b68089a6c7f60458390860e044 (patch)
treeeb7e2ecd9ed875ed4d3a050b95ed3d77bbde762b
parenteb31628e37a0a4e01fffd79dcc7f815d2357f53a (diff)
netfilter: nf_tables: complete net namespace support
Register family per netnamespace to ensure that sets are only visible in its approapriate namespace. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/net/net_namespace.h4
-rw-r--r--include/net/netfilter/nf_tables.h4
-rw-r--r--include/net/netns/nftables.h15
-rw-r--r--net/bridge/netfilter/nf_tables_bridge.c32
-rw-r--r--net/ipv4/netfilter/nf_tables_ipv4.c32
-rw-r--r--net/ipv6/netfilter/nf_tables_ipv6.c33
-rw-r--r--net/netfilter/nf_tables_api.c83
7 files changed, 168 insertions, 35 deletions
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index bcc4a8ed4450..da68c9a90ac5 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -22,6 +22,7 @@
22#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 22#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
23#include <net/netns/conntrack.h> 23#include <net/netns/conntrack.h>
24#endif 24#endif
25#include <net/netns/nftables.h>
25#include <net/netns/xfrm.h> 26#include <net/netns/xfrm.h>
26 27
27struct user_namespace; 28struct user_namespace;
@@ -101,6 +102,9 @@ struct net {
101#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 102#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
102 struct netns_ct ct; 103 struct netns_ct ct;
103#endif 104#endif
105#if defined(CONFIG_NF_TABLES) || defined(CONFIG_NF_TABLES_MODULE)
106 struct netns_nftables nft;
107#endif
104#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) 108#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
105 struct netns_nf_frag nf_frag; 109 struct netns_nf_frag nf_frag;
106#endif 110#endif
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index a68f45f0fe2e..d3272e943aac 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -68,6 +68,7 @@ static inline void nft_data_debug(const struct nft_data *data)
68/** 68/**
69 * struct nft_ctx - nf_tables rule/set context 69 * struct nft_ctx - nf_tables rule/set context
70 * 70 *
71 * @net: net namespace
71 * @skb: netlink skb 72 * @skb: netlink skb
72 * @nlh: netlink message header 73 * @nlh: netlink message header
73 * @afi: address family info 74 * @afi: address family info
@@ -76,6 +77,7 @@ static inline void nft_data_debug(const struct nft_data *data)
76 * @nla: netlink attributes 77 * @nla: netlink attributes
77 */ 78 */
78struct nft_ctx { 79struct nft_ctx {
80 struct net *net;
79 const struct sk_buff *skb; 81 const struct sk_buff *skb;
80 const struct nlmsghdr *nlh; 82 const struct nlmsghdr *nlh;
81 const struct nft_af_info *afi; 83 const struct nft_af_info *afi;
@@ -462,7 +464,7 @@ struct nft_af_info {
462 nf_hookfn *hooks[NF_MAX_HOOKS]; 464 nf_hookfn *hooks[NF_MAX_HOOKS];
463}; 465};
464 466
465extern int nft_register_afinfo(struct nft_af_info *); 467extern int nft_register_afinfo(struct net *, struct nft_af_info *);
466extern void nft_unregister_afinfo(struct nft_af_info *); 468extern void nft_unregister_afinfo(struct nft_af_info *);
467 469
468struct nf_chain_type { 470struct nf_chain_type {
diff --git a/include/net/netns/nftables.h b/include/net/netns/nftables.h
new file mode 100644
index 000000000000..a98b1c5d9913
--- /dev/null
+++ b/include/net/netns/nftables.h
@@ -0,0 +1,15 @@
1#ifndef _NETNS_NFTABLES_H_
2#define _NETNS_NFTABLES_H_
3
4#include <linux/list.h>
5
6struct nft_af_info;
7
8struct netns_nftables {
9 struct list_head af_info;
10 struct nft_af_info *ipv4;
11 struct nft_af_info *ipv6;
12 struct nft_af_info *bridge;
13};
14
15#endif
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c
index bc5c21c911c0..e8cb016fa34d 100644
--- a/net/bridge/netfilter/nf_tables_bridge.c
+++ b/net/bridge/netfilter/nf_tables_bridge.c
@@ -19,14 +19,42 @@ static struct nft_af_info nft_af_bridge __read_mostly = {
19 .owner = THIS_MODULE, 19 .owner = THIS_MODULE,
20}; 20};
21 21
22static int nf_tables_bridge_init_net(struct net *net)
23{
24 net->nft.bridge = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
25 if (net->nft.bridge == NULL)
26 return -ENOMEM;
27
28 memcpy(net->nft.bridge, &nft_af_bridge, sizeof(nft_af_bridge));
29
30 if (nft_register_afinfo(net, net->nft.bridge) < 0)
31 goto err;
32
33 return 0;
34err:
35 kfree(net->nft.bridge);
36 return -ENOMEM;
37}
38
39static void nf_tables_bridge_exit_net(struct net *net)
40{
41 nft_unregister_afinfo(net->nft.bridge);
42 kfree(net->nft.bridge);
43}
44
45static struct pernet_operations nf_tables_bridge_net_ops = {
46 .init = nf_tables_bridge_init_net,
47 .exit = nf_tables_bridge_exit_net,
48};
49
22static int __init nf_tables_bridge_init(void) 50static int __init nf_tables_bridge_init(void)
23{ 51{
24 return nft_register_afinfo(&nft_af_bridge); 52 return register_pernet_subsys(&nf_tables_bridge_net_ops);
25} 53}
26 54
27static void __exit nf_tables_bridge_exit(void) 55static void __exit nf_tables_bridge_exit(void)
28{ 56{
29 nft_unregister_afinfo(&nft_af_bridge); 57 return unregister_pernet_subsys(&nf_tables_bridge_net_ops);
30} 58}
31 59
32module_init(nf_tables_bridge_init); 60module_init(nf_tables_bridge_init);
diff --git a/net/ipv4/netfilter/nf_tables_ipv4.c b/net/ipv4/netfilter/nf_tables_ipv4.c
index c61cffb9b760..8f7536be1322 100644
--- a/net/ipv4/netfilter/nf_tables_ipv4.c
+++ b/net/ipv4/netfilter/nf_tables_ipv4.c
@@ -14,6 +14,7 @@
14#include <linux/ip.h> 14#include <linux/ip.h>
15#include <linux/netfilter_ipv4.h> 15#include <linux/netfilter_ipv4.h>
16#include <net/netfilter/nf_tables.h> 16#include <net/netfilter/nf_tables.h>
17#include <net/net_namespace.h>
17#include <net/ip.h> 18#include <net/ip.h>
18#include <net/net_namespace.h> 19#include <net/net_namespace.h>
19#include <net/netfilter/nf_tables_ipv4.h> 20#include <net/netfilter/nf_tables_ipv4.h>
@@ -47,6 +48,33 @@ static struct nft_af_info nft_af_ipv4 __read_mostly = {
47 }, 48 },
48}; 49};
49 50
51static int nf_tables_ipv4_init_net(struct net *net)
52{
53 net->nft.ipv4 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
54 if (net->nft.ipv4 == NULL)
55 return -ENOMEM;
56
57 memcpy(net->nft.ipv4, &nft_af_ipv4, sizeof(nft_af_ipv4));
58
59 if (nft_register_afinfo(net, net->nft.ipv4) < 0)
60 goto err;
61
62 return 0;
63err:
64 kfree(net->nft.ipv4);
65 return -ENOMEM;
66}
67
68static void nf_tables_ipv4_exit_net(struct net *net)
69{
70 nft_unregister_afinfo(net->nft.ipv4);
71 kfree(net->nft.ipv4);
72}
73
74static struct pernet_operations nf_tables_ipv4_net_ops = {
75 .init = nf_tables_ipv4_init_net,
76 .exit = nf_tables_ipv4_exit_net,
77};
50 78
51static unsigned int 79static unsigned int
52nft_do_chain_ipv4(const struct nf_hook_ops *ops, 80nft_do_chain_ipv4(const struct nf_hook_ops *ops,
@@ -83,12 +111,12 @@ static struct nf_chain_type filter_ipv4 = {
83static int __init nf_tables_ipv4_init(void) 111static int __init nf_tables_ipv4_init(void)
84{ 112{
85 nft_register_chain_type(&filter_ipv4); 113 nft_register_chain_type(&filter_ipv4);
86 return nft_register_afinfo(&nft_af_ipv4); 114 return register_pernet_subsys(&nf_tables_ipv4_net_ops);
87} 115}
88 116
89static void __exit nf_tables_ipv4_exit(void) 117static void __exit nf_tables_ipv4_exit(void)
90{ 118{
91 nft_unregister_afinfo(&nft_af_ipv4); 119 unregister_pernet_subsys(&nf_tables_ipv4_net_ops);
92 nft_unregister_chain_type(&filter_ipv4); 120 nft_unregister_chain_type(&filter_ipv4);
93} 121}
94 122
diff --git a/net/ipv6/netfilter/nf_tables_ipv6.c b/net/ipv6/netfilter/nf_tables_ipv6.c
index 42f905a808a3..d77db8a13505 100644
--- a/net/ipv6/netfilter/nf_tables_ipv6.c
+++ b/net/ipv6/netfilter/nf_tables_ipv6.c
@@ -45,6 +45,34 @@ static struct nft_af_info nft_af_ipv6 __read_mostly = {
45 }, 45 },
46}; 46};
47 47
48static int nf_tables_ipv6_init_net(struct net *net)
49{
50 net->nft.ipv6 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
51 if (net->nft.ipv6 == NULL)
52 return -ENOMEM;
53
54 memcpy(net->nft.ipv6, &nft_af_ipv6, sizeof(nft_af_ipv6));
55
56 if (nft_register_afinfo(net, net->nft.ipv6) < 0)
57 goto err;
58
59 return 0;
60err:
61 kfree(net->nft.ipv6);
62 return -ENOMEM;
63}
64
65static void nf_tables_ipv6_exit_net(struct net *net)
66{
67 nft_unregister_afinfo(net->nft.ipv6);
68 kfree(net->nft.ipv6);
69}
70
71static struct pernet_operations nf_tables_ipv6_net_ops = {
72 .init = nf_tables_ipv6_init_net,
73 .exit = nf_tables_ipv6_exit_net,
74};
75
48static unsigned int 76static unsigned int
49nft_do_chain_ipv6(const struct nf_hook_ops *ops, 77nft_do_chain_ipv6(const struct nf_hook_ops *ops,
50 struct sk_buff *skb, 78 struct sk_buff *skb,
@@ -82,11 +110,12 @@ static struct nf_chain_type filter_ipv6 = {
82static int __init nf_tables_ipv6_init(void) 110static int __init nf_tables_ipv6_init(void)
83{ 111{
84 nft_register_chain_type(&filter_ipv6); 112 nft_register_chain_type(&filter_ipv6);
85 return nft_register_afinfo(&nft_af_ipv6); 113 return register_pernet_subsys(&nf_tables_ipv6_net_ops);
86} 114}
115
87static void __exit nf_tables_ipv6_exit(void) 116static void __exit nf_tables_ipv6_exit(void)
88{ 117{
89 nft_unregister_afinfo(&nft_af_ipv6); 118 unregister_pernet_subsys(&nf_tables_ipv6_net_ops);
90 nft_unregister_chain_type(&filter_ipv6); 119 nft_unregister_chain_type(&filter_ipv6);
91} 120}
92 121
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index a4dd7ce5ec3e..e1ee85047ec1 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -18,9 +18,9 @@
18#include <linux/netfilter/nf_tables.h> 18#include <linux/netfilter/nf_tables.h>
19#include <net/netfilter/nf_tables_core.h> 19#include <net/netfilter/nf_tables_core.h>
20#include <net/netfilter/nf_tables.h> 20#include <net/netfilter/nf_tables.h>
21#include <net/net_namespace.h>
21#include <net/sock.h> 22#include <net/sock.h>
22 23
23static LIST_HEAD(nf_tables_afinfo);
24static LIST_HEAD(nf_tables_expressions); 24static LIST_HEAD(nf_tables_expressions);
25 25
26/** 26/**
@@ -31,11 +31,11 @@ static LIST_HEAD(nf_tables_expressions);
31 * Register the address family for use with nf_tables. Returns zero on 31 * Register the address family for use with nf_tables. Returns zero on
32 * success or a negative errno code otherwise. 32 * success or a negative errno code otherwise.
33 */ 33 */
34int nft_register_afinfo(struct nft_af_info *afi) 34int nft_register_afinfo(struct net *net, struct nft_af_info *afi)
35{ 35{
36 INIT_LIST_HEAD(&afi->tables); 36 INIT_LIST_HEAD(&afi->tables);
37 nfnl_lock(NFNL_SUBSYS_NFTABLES); 37 nfnl_lock(NFNL_SUBSYS_NFTABLES);
38 list_add_tail(&afi->list, &nf_tables_afinfo); 38 list_add_tail(&afi->list, &net->nft.af_info);
39 nfnl_unlock(NFNL_SUBSYS_NFTABLES); 39 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
40 return 0; 40 return 0;
41} 41}
@@ -56,22 +56,23 @@ void nft_unregister_afinfo(struct nft_af_info *afi)
56} 56}
57EXPORT_SYMBOL_GPL(nft_unregister_afinfo); 57EXPORT_SYMBOL_GPL(nft_unregister_afinfo);
58 58
59static struct nft_af_info *nft_afinfo_lookup(int family) 59static struct nft_af_info *nft_afinfo_lookup(struct net *net, int family)
60{ 60{
61 struct nft_af_info *afi; 61 struct nft_af_info *afi;
62 62
63 list_for_each_entry(afi, &nf_tables_afinfo, list) { 63 list_for_each_entry(afi, &net->nft.af_info, list) {
64 if (afi->family == family) 64 if (afi->family == family)
65 return afi; 65 return afi;
66 } 66 }
67 return NULL; 67 return NULL;
68} 68}
69 69
70static struct nft_af_info *nf_tables_afinfo_lookup(int family, bool autoload) 70static struct nft_af_info *
71nf_tables_afinfo_lookup(struct net *net, int family, bool autoload)
71{ 72{
72 struct nft_af_info *afi; 73 struct nft_af_info *afi;
73 74
74 afi = nft_afinfo_lookup(family); 75 afi = nft_afinfo_lookup(net, family);
75 if (afi != NULL) 76 if (afi != NULL)
76 return afi; 77 return afi;
77#ifdef CONFIG_MODULES 78#ifdef CONFIG_MODULES
@@ -79,7 +80,7 @@ static struct nft_af_info *nf_tables_afinfo_lookup(int family, bool autoload)
79 nfnl_unlock(NFNL_SUBSYS_NFTABLES); 80 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
80 request_module("nft-afinfo-%u", family); 81 request_module("nft-afinfo-%u", family);
81 nfnl_lock(NFNL_SUBSYS_NFTABLES); 82 nfnl_lock(NFNL_SUBSYS_NFTABLES);
82 afi = nft_afinfo_lookup(family); 83 afi = nft_afinfo_lookup(net, family);
83 if (afi != NULL) 84 if (afi != NULL)
84 return ERR_PTR(-EAGAIN); 85 return ERR_PTR(-EAGAIN);
85 } 86 }
@@ -232,9 +233,10 @@ static int nf_tables_dump_tables(struct sk_buff *skb,
232 const struct nft_af_info *afi; 233 const struct nft_af_info *afi;
233 const struct nft_table *table; 234 const struct nft_table *table;
234 unsigned int idx = 0, s_idx = cb->args[0]; 235 unsigned int idx = 0, s_idx = cb->args[0];
236 struct net *net = sock_net(skb->sk);
235 int family = nfmsg->nfgen_family; 237 int family = nfmsg->nfgen_family;
236 238
237 list_for_each_entry(afi, &nf_tables_afinfo, list) { 239 list_for_each_entry(afi, &net->nft.af_info, list) {
238 if (family != NFPROTO_UNSPEC && family != afi->family) 240 if (family != NFPROTO_UNSPEC && family != afi->family)
239 continue; 241 continue;
240 242
@@ -268,6 +270,7 @@ static int nf_tables_gettable(struct sock *nlsk, struct sk_buff *skb,
268 const struct nft_af_info *afi; 270 const struct nft_af_info *afi;
269 const struct nft_table *table; 271 const struct nft_table *table;
270 struct sk_buff *skb2; 272 struct sk_buff *skb2;
273 struct net *net = sock_net(skb->sk);
271 int family = nfmsg->nfgen_family; 274 int family = nfmsg->nfgen_family;
272 int err; 275 int err;
273 276
@@ -278,7 +281,7 @@ static int nf_tables_gettable(struct sock *nlsk, struct sk_buff *skb,
278 return netlink_dump_start(nlsk, skb, nlh, &c); 281 return netlink_dump_start(nlsk, skb, nlh, &c);
279 } 282 }
280 283
281 afi = nf_tables_afinfo_lookup(family, false); 284 afi = nf_tables_afinfo_lookup(net, family, false);
282 if (IS_ERR(afi)) 285 if (IS_ERR(afi))
283 return PTR_ERR(afi); 286 return PTR_ERR(afi);
284 287
@@ -379,9 +382,10 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
379 const struct nlattr *name; 382 const struct nlattr *name;
380 struct nft_af_info *afi; 383 struct nft_af_info *afi;
381 struct nft_table *table; 384 struct nft_table *table;
385 struct net *net = sock_net(skb->sk);
382 int family = nfmsg->nfgen_family; 386 int family = nfmsg->nfgen_family;
383 387
384 afi = nf_tables_afinfo_lookup(family, true); 388 afi = nf_tables_afinfo_lookup(net, family, true);
385 if (IS_ERR(afi)) 389 if (IS_ERR(afi))
386 return PTR_ERR(afi); 390 return PTR_ERR(afi);
387 391
@@ -433,9 +437,10 @@ static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb,
433 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 437 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
434 struct nft_af_info *afi; 438 struct nft_af_info *afi;
435 struct nft_table *table; 439 struct nft_table *table;
440 struct net *net = sock_net(skb->sk);
436 int family = nfmsg->nfgen_family; 441 int family = nfmsg->nfgen_family;
437 442
438 afi = nf_tables_afinfo_lookup(family, false); 443 afi = nf_tables_afinfo_lookup(net, family, false);
439 if (IS_ERR(afi)) 444 if (IS_ERR(afi))
440 return PTR_ERR(afi); 445 return PTR_ERR(afi);
441 446
@@ -663,9 +668,10 @@ static int nf_tables_dump_chains(struct sk_buff *skb,
663 const struct nft_table *table; 668 const struct nft_table *table;
664 const struct nft_chain *chain; 669 const struct nft_chain *chain;
665 unsigned int idx = 0, s_idx = cb->args[0]; 670 unsigned int idx = 0, s_idx = cb->args[0];
671 struct net *net = sock_net(skb->sk);
666 int family = nfmsg->nfgen_family; 672 int family = nfmsg->nfgen_family;
667 673
668 list_for_each_entry(afi, &nf_tables_afinfo, list) { 674 list_for_each_entry(afi, &net->nft.af_info, list) {
669 if (family != NFPROTO_UNSPEC && family != afi->family) 675 if (family != NFPROTO_UNSPEC && family != afi->family)
670 continue; 676 continue;
671 677
@@ -702,6 +708,7 @@ static int nf_tables_getchain(struct sock *nlsk, struct sk_buff *skb,
702 const struct nft_table *table; 708 const struct nft_table *table;
703 const struct nft_chain *chain; 709 const struct nft_chain *chain;
704 struct sk_buff *skb2; 710 struct sk_buff *skb2;
711 struct net *net = sock_net(skb->sk);
705 int family = nfmsg->nfgen_family; 712 int family = nfmsg->nfgen_family;
706 int err; 713 int err;
707 714
@@ -712,7 +719,7 @@ static int nf_tables_getchain(struct sock *nlsk, struct sk_buff *skb,
712 return netlink_dump_start(nlsk, skb, nlh, &c); 719 return netlink_dump_start(nlsk, skb, nlh, &c);
713 } 720 }
714 721
715 afi = nf_tables_afinfo_lookup(family, false); 722 afi = nf_tables_afinfo_lookup(net, family, false);
716 if (IS_ERR(afi)) 723 if (IS_ERR(afi))
717 return PTR_ERR(afi); 724 return PTR_ERR(afi);
718 725
@@ -813,6 +820,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
813 struct nft_chain *chain; 820 struct nft_chain *chain;
814 struct nft_base_chain *basechain = NULL; 821 struct nft_base_chain *basechain = NULL;
815 struct nlattr *ha[NFTA_HOOK_MAX + 1]; 822 struct nlattr *ha[NFTA_HOOK_MAX + 1];
823 struct net *net = sock_net(skb->sk);
816 int family = nfmsg->nfgen_family; 824 int family = nfmsg->nfgen_family;
817 u64 handle = 0; 825 u64 handle = 0;
818 int err; 826 int err;
@@ -820,7 +828,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
820 828
821 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 829 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
822 830
823 afi = nf_tables_afinfo_lookup(family, true); 831 afi = nf_tables_afinfo_lookup(net, family, true);
824 if (IS_ERR(afi)) 832 if (IS_ERR(afi))
825 return PTR_ERR(afi); 833 return PTR_ERR(afi);
826 834
@@ -1010,9 +1018,10 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
1010 const struct nft_af_info *afi; 1018 const struct nft_af_info *afi;
1011 struct nft_table *table; 1019 struct nft_table *table;
1012 struct nft_chain *chain; 1020 struct nft_chain *chain;
1021 struct net *net = sock_net(skb->sk);
1013 int family = nfmsg->nfgen_family; 1022 int family = nfmsg->nfgen_family;
1014 1023
1015 afi = nf_tables_afinfo_lookup(family, false); 1024 afi = nf_tables_afinfo_lookup(net, family, false);
1016 if (IS_ERR(afi)) 1025 if (IS_ERR(afi))
1017 return PTR_ERR(afi); 1026 return PTR_ERR(afi);
1018 1027
@@ -1050,6 +1059,7 @@ static void nft_ctx_init(struct nft_ctx *ctx,
1050 const struct nft_chain *chain, 1059 const struct nft_chain *chain,
1051 const struct nlattr * const *nla) 1060 const struct nlattr * const *nla)
1052{ 1061{
1062 ctx->net = sock_net(skb->sk);
1053 ctx->skb = skb; 1063 ctx->skb = skb;
1054 ctx->nlh = nlh; 1064 ctx->nlh = nlh;
1055 ctx->afi = afi; 1065 ctx->afi = afi;
@@ -1361,9 +1371,10 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
1361 const struct nft_chain *chain; 1371 const struct nft_chain *chain;
1362 const struct nft_rule *rule; 1372 const struct nft_rule *rule;
1363 unsigned int idx = 0, s_idx = cb->args[0]; 1373 unsigned int idx = 0, s_idx = cb->args[0];
1374 struct net *net = sock_net(skb->sk);
1364 int family = nfmsg->nfgen_family; 1375 int family = nfmsg->nfgen_family;
1365 1376
1366 list_for_each_entry(afi, &nf_tables_afinfo, list) { 1377 list_for_each_entry(afi, &net->nft.af_info, list) {
1367 if (family != NFPROTO_UNSPEC && family != afi->family) 1378 if (family != NFPROTO_UNSPEC && family != afi->family)
1368 continue; 1379 continue;
1369 1380
@@ -1402,6 +1413,7 @@ static int nf_tables_getrule(struct sock *nlsk, struct sk_buff *skb,
1402 const struct nft_chain *chain; 1413 const struct nft_chain *chain;
1403 const struct nft_rule *rule; 1414 const struct nft_rule *rule;
1404 struct sk_buff *skb2; 1415 struct sk_buff *skb2;
1416 struct net *net = sock_net(skb->sk);
1405 int family = nfmsg->nfgen_family; 1417 int family = nfmsg->nfgen_family;
1406 int err; 1418 int err;
1407 1419
@@ -1412,7 +1424,7 @@ static int nf_tables_getrule(struct sock *nlsk, struct sk_buff *skb,
1412 return netlink_dump_start(nlsk, skb, nlh, &c); 1424 return netlink_dump_start(nlsk, skb, nlh, &c);
1413 } 1425 }
1414 1426
1415 afi = nf_tables_afinfo_lookup(family, false); 1427 afi = nf_tables_afinfo_lookup(net, family, false);
1416 if (IS_ERR(afi)) 1428 if (IS_ERR(afi))
1417 return PTR_ERR(afi); 1429 return PTR_ERR(afi);
1418 1430
@@ -1477,6 +1489,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
1477{ 1489{
1478 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1490 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
1479 const struct nft_af_info *afi; 1491 const struct nft_af_info *afi;
1492 struct net *net = sock_net(skb->sk);
1480 struct nft_table *table; 1493 struct nft_table *table;
1481 struct nft_chain *chain; 1494 struct nft_chain *chain;
1482 struct nft_rule *rule, *old_rule = NULL; 1495 struct nft_rule *rule, *old_rule = NULL;
@@ -1490,7 +1503,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
1490 1503
1491 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 1504 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
1492 1505
1493 afi = nf_tables_afinfo_lookup(nfmsg->nfgen_family, create); 1506 afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create);
1494 if (IS_ERR(afi)) 1507 if (IS_ERR(afi))
1495 return PTR_ERR(afi); 1508 return PTR_ERR(afi);
1496 1509
@@ -1585,12 +1598,13 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
1585{ 1598{
1586 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1599 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
1587 const struct nft_af_info *afi; 1600 const struct nft_af_info *afi;
1601 struct net *net = sock_net(skb->sk);
1588 const struct nft_table *table; 1602 const struct nft_table *table;
1589 struct nft_chain *chain; 1603 struct nft_chain *chain;
1590 struct nft_rule *rule, *tmp; 1604 struct nft_rule *rule, *tmp;
1591 int family = nfmsg->nfgen_family; 1605 int family = nfmsg->nfgen_family;
1592 1606
1593 afi = nf_tables_afinfo_lookup(family, false); 1607 afi = nf_tables_afinfo_lookup(net, family, false);
1594 if (IS_ERR(afi)) 1608 if (IS_ERR(afi))
1595 return PTR_ERR(afi); 1609 return PTR_ERR(afi);
1596 1610
@@ -1697,11 +1711,12 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx,
1697 const struct nlmsghdr *nlh, 1711 const struct nlmsghdr *nlh,
1698 const struct nlattr * const nla[]) 1712 const struct nlattr * const nla[])
1699{ 1713{
1714 struct net *net = sock_net(skb->sk);
1700 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1715 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
1701 const struct nft_af_info *afi; 1716 const struct nft_af_info *afi;
1702 const struct nft_table *table = NULL; 1717 const struct nft_table *table = NULL;
1703 1718
1704 afi = nf_tables_afinfo_lookup(nfmsg->nfgen_family, false); 1719 afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false);
1705 if (IS_ERR(afi)) 1720 if (IS_ERR(afi))
1706 return PTR_ERR(afi); 1721 return PTR_ERR(afi);
1707 1722
@@ -1818,12 +1833,11 @@ static int nf_tables_set_notify(const struct nft_ctx *ctx,
1818{ 1833{
1819 struct sk_buff *skb; 1834 struct sk_buff *skb;
1820 u32 portid = NETLINK_CB(ctx->skb).portid; 1835 u32 portid = NETLINK_CB(ctx->skb).portid;
1821 struct net *net = sock_net(ctx->skb->sk);
1822 bool report; 1836 bool report;
1823 int err; 1837 int err;
1824 1838
1825 report = nlmsg_report(ctx->nlh); 1839 report = nlmsg_report(ctx->nlh);
1826 if (!report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) 1840 if (!report && !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
1827 return 0; 1841 return 0;
1828 1842
1829 err = -ENOBUFS; 1843 err = -ENOBUFS;
@@ -1837,11 +1851,11 @@ static int nf_tables_set_notify(const struct nft_ctx *ctx,
1837 goto err; 1851 goto err;
1838 } 1852 }
1839 1853
1840 err = nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, report, 1854 err = nfnetlink_send(skb, ctx->net, portid, NFNLGRP_NFTABLES, report,
1841 GFP_KERNEL); 1855 GFP_KERNEL);
1842err: 1856err:
1843 if (err < 0) 1857 if (err < 0)
1844 nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, err); 1858 nfnetlink_set_err(ctx->net, portid, NFNLGRP_NFTABLES, err);
1845 return err; 1859 return err;
1846} 1860}
1847 1861
@@ -1974,6 +1988,7 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
1974 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1988 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
1975 const struct nft_set_ops *ops; 1989 const struct nft_set_ops *ops;
1976 const struct nft_af_info *afi; 1990 const struct nft_af_info *afi;
1991 struct net *net = sock_net(skb->sk);
1977 struct nft_table *table; 1992 struct nft_table *table;
1978 struct nft_set *set; 1993 struct nft_set *set;
1979 struct nft_ctx ctx; 1994 struct nft_ctx ctx;
@@ -2032,7 +2047,7 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
2032 2047
2033 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 2048 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
2034 2049
2035 afi = nf_tables_afinfo_lookup(nfmsg->nfgen_family, create); 2050 afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create);
2036 if (IS_ERR(afi)) 2051 if (IS_ERR(afi))
2037 return PTR_ERR(afi); 2052 return PTR_ERR(afi);
2038 2053
@@ -2219,8 +2234,9 @@ static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx,
2219 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2234 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
2220 const struct nft_af_info *afi; 2235 const struct nft_af_info *afi;
2221 const struct nft_table *table; 2236 const struct nft_table *table;
2237 struct net *net = sock_net(skb->sk);
2222 2238
2223 afi = nf_tables_afinfo_lookup(nfmsg->nfgen_family, false); 2239 afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false);
2224 if (IS_ERR(afi)) 2240 if (IS_ERR(afi))
2225 return PTR_ERR(afi); 2241 return PTR_ERR(afi);
2226 2242
@@ -3011,6 +3027,16 @@ int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
3011} 3027}
3012EXPORT_SYMBOL_GPL(nft_data_dump); 3028EXPORT_SYMBOL_GPL(nft_data_dump);
3013 3029
3030static int nf_tables_init_net(struct net *net)
3031{
3032 INIT_LIST_HEAD(&net->nft.af_info);
3033 return 0;
3034}
3035
3036static struct pernet_operations nf_tables_net_ops = {
3037 .init = nf_tables_init_net,
3038};
3039
3014static int __init nf_tables_module_init(void) 3040static int __init nf_tables_module_init(void)
3015{ 3041{
3016 int err; 3042 int err;
@@ -3031,7 +3057,7 @@ static int __init nf_tables_module_init(void)
3031 goto err3; 3057 goto err3;
3032 3058
3033 pr_info("nf_tables: (c) 2007-2009 Patrick McHardy <kaber@trash.net>\n"); 3059 pr_info("nf_tables: (c) 2007-2009 Patrick McHardy <kaber@trash.net>\n");
3034 return 0; 3060 return register_pernet_subsys(&nf_tables_net_ops);
3035err3: 3061err3:
3036 nf_tables_core_module_exit(); 3062 nf_tables_core_module_exit();
3037err2: 3063err2:
@@ -3042,6 +3068,7 @@ err1:
3042 3068
3043static void __exit nf_tables_module_exit(void) 3069static void __exit nf_tables_module_exit(void)
3044{ 3070{
3071 unregister_pernet_subsys(&nf_tables_net_ops);
3045 nfnetlink_subsys_unregister(&nf_tables_subsys); 3072 nfnetlink_subsys_unregister(&nf_tables_subsys);
3046 nf_tables_core_module_exit(); 3073 nf_tables_core_module_exit();
3047 kfree(info); 3074 kfree(info);