Skip to content

Commit fdacd57

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: x_tables: never register tables by default
For historical reasons x_tables still register tables by default in the initial namespace. Only newly created net namespaces add the hook on demand. This means that the init_net always pays hook cost, even if no filtering rules are added (e.g. only used inside a single netns). Note that the hooks are added even when 'iptables -L' is called. This is because there is no way to tell 'iptables -A' and 'iptables -L' apart at kernel level. The only solution would be to register the table, but delay hook registration until the first rule gets added (or policy gets changed). That however means that counters are not hooked either, so 'iptables -L' would always show 0-counters even when traffic is flowing which might be unexpected. This keeps table and hook registration consistent with what is already done in non-init netns: first iptables(-save) invocation registers both table and hooks. This applies the same solution adopted for ebtables. All tables register a template that contains the l3 family, the name and a constructor function that is called when the initial table has to be added. Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 9344988 commit fdacd57

File tree

13 files changed

+204
-135
lines changed

13 files changed

+204
-135
lines changed

include/linux/netfilter/x_tables.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,6 @@ struct xt_table {
238238
u_int8_t af; /* address/protocol family */
239239
int priority; /* hook order */
240240

241-
/* called when table is needed in the given netns */
242-
int (*table_init)(struct net *net);
243-
244241
/* A unique name... */
245242
const char name[XT_TABLE_MAXNAMELEN];
246243
};
@@ -452,6 +449,9 @@ xt_get_per_cpu_counter(struct xt_counters *cnt, unsigned int cpu)
452449

453450
struct nf_hook_ops *xt_hook_ops_alloc(const struct xt_table *, nf_hookfn *);
454451

452+
int xt_register_template(const struct xt_table *t, int(*table_init)(struct net *net));
453+
void xt_unregister_template(const struct xt_table *t);
454+
455455
#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
456456
#include <net/compat.h>
457457

net/ipv4/netfilter/arptable_filter.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,12 @@ MODULE_DESCRIPTION("arptables filter table");
1818
#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \
1919
(1 << NF_ARP_FORWARD))
2020

21-
static int __net_init arptable_filter_table_init(struct net *net);
22-
2321
static const struct xt_table packet_filter = {
2422
.name = "filter",
2523
.valid_hooks = FILTER_VALID_HOOKS,
2624
.me = THIS_MODULE,
2725
.af = NFPROTO_ARP,
2826
.priority = NF_IP_PRI_FILTER,
29-
.table_init = arptable_filter_table_init,
3027
};
3128

3229
/* The work comes in here from netfilter.c */
@@ -39,7 +36,7 @@ arptable_filter_hook(void *priv, struct sk_buff *skb,
3936

4037
static struct nf_hook_ops *arpfilter_ops __read_mostly;
4138

42-
static int __net_init arptable_filter_table_init(struct net *net)
39+
static int arptable_filter_table_init(struct net *net)
4340
{
4441
struct arpt_replace *repl;
4542
int err;
@@ -69,30 +66,32 @@ static struct pernet_operations arptable_filter_net_ops = {
6966

7067
static int __init arptable_filter_init(void)
7168
{
72-
int ret;
69+
int ret = xt_register_template(&packet_filter,
70+
arptable_filter_table_init);
71+
72+
if (ret < 0)
73+
return ret;
7374

7475
arpfilter_ops = xt_hook_ops_alloc(&packet_filter, arptable_filter_hook);
75-
if (IS_ERR(arpfilter_ops))
76+
if (IS_ERR(arpfilter_ops)) {
77+
xt_unregister_template(&packet_filter);
7678
return PTR_ERR(arpfilter_ops);
79+
}
7780

7881
ret = register_pernet_subsys(&arptable_filter_net_ops);
7982
if (ret < 0) {
83+
xt_unregister_template(&packet_filter);
8084
kfree(arpfilter_ops);
8185
return ret;
8286
}
8387

84-
ret = arptable_filter_table_init(&init_net);
85-
if (ret) {
86-
unregister_pernet_subsys(&arptable_filter_net_ops);
87-
kfree(arpfilter_ops);
88-
}
89-
9088
return ret;
9189
}
9290

9391
static void __exit arptable_filter_fini(void)
9492
{
9593
unregister_pernet_subsys(&arptable_filter_net_ops);
94+
xt_unregister_template(&packet_filter);
9695
kfree(arpfilter_ops);
9796
}
9897

net/ipv4/netfilter/iptable_filter.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,13 @@ MODULE_DESCRIPTION("iptables filter table");
1919
#define FILTER_VALID_HOOKS ((1 << NF_INET_LOCAL_IN) | \
2020
(1 << NF_INET_FORWARD) | \
2121
(1 << NF_INET_LOCAL_OUT))
22-
static int __net_init iptable_filter_table_init(struct net *net);
2322

2423
static const struct xt_table packet_filter = {
2524
.name = "filter",
2625
.valid_hooks = FILTER_VALID_HOOKS,
2726
.me = THIS_MODULE,
2827
.af = NFPROTO_IPV4,
2928
.priority = NF_IP_PRI_FILTER,
30-
.table_init = iptable_filter_table_init,
3129
};
3230

3331
static unsigned int
@@ -43,7 +41,7 @@ static struct nf_hook_ops *filter_ops __read_mostly;
4341
static bool forward __read_mostly = true;
4442
module_param(forward, bool, 0000);
4543

46-
static int __net_init iptable_filter_table_init(struct net *net)
44+
static int iptable_filter_table_init(struct net *net)
4745
{
4846
struct ipt_replace *repl;
4947
int err;
@@ -62,7 +60,7 @@ static int __net_init iptable_filter_table_init(struct net *net)
6260

6361
static int __net_init iptable_filter_net_init(struct net *net)
6462
{
65-
if (net == &init_net || !forward)
63+
if (!forward)
6664
return iptable_filter_table_init(net);
6765

6866
return 0;
@@ -86,22 +84,32 @@ static struct pernet_operations iptable_filter_net_ops = {
8684

8785
static int __init iptable_filter_init(void)
8886
{
89-
int ret;
87+
int ret = xt_register_template(&packet_filter,
88+
iptable_filter_table_init);
89+
90+
if (ret < 0)
91+
return ret;
9092

9193
filter_ops = xt_hook_ops_alloc(&packet_filter, iptable_filter_hook);
92-
if (IS_ERR(filter_ops))
94+
if (IS_ERR(filter_ops)) {
95+
xt_unregister_template(&packet_filter);
9396
return PTR_ERR(filter_ops);
97+
}
9498

9599
ret = register_pernet_subsys(&iptable_filter_net_ops);
96-
if (ret < 0)
100+
if (ret < 0) {
101+
xt_unregister_template(&packet_filter);
97102
kfree(filter_ops);
103+
return ret;
104+
}
98105

99-
return ret;
106+
return 0;
100107
}
101108

102109
static void __exit iptable_filter_fini(void)
103110
{
104111
unregister_pernet_subsys(&iptable_filter_net_ops);
112+
xt_unregister_template(&packet_filter);
105113
kfree(filter_ops);
106114
}
107115

net/ipv4/netfilter/iptable_mangle.c

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,12 @@ MODULE_DESCRIPTION("iptables mangle table");
2525
(1 << NF_INET_LOCAL_OUT) | \
2626
(1 << NF_INET_POST_ROUTING))
2727

28-
static int __net_init iptable_mangle_table_init(struct net *net);
29-
3028
static const struct xt_table packet_mangler = {
3129
.name = "mangle",
3230
.valid_hooks = MANGLE_VALID_HOOKS,
3331
.me = THIS_MODULE,
3432
.af = NFPROTO_IPV4,
3533
.priority = NF_IP_PRI_MANGLE,
36-
.table_init = iptable_mangle_table_init,
3734
};
3835

3936
static unsigned int
@@ -83,7 +80,7 @@ iptable_mangle_hook(void *priv,
8380
}
8481

8582
static struct nf_hook_ops *mangle_ops __read_mostly;
86-
static int __net_init iptable_mangle_table_init(struct net *net)
83+
static int iptable_mangle_table_init(struct net *net)
8784
{
8885
struct ipt_replace *repl;
8986
int ret;
@@ -113,32 +110,30 @@ static struct pernet_operations iptable_mangle_net_ops = {
113110

114111
static int __init iptable_mangle_init(void)
115112
{
116-
int ret;
113+
int ret = xt_register_template(&packet_mangler,
114+
iptable_mangle_table_init);
117115

118116
mangle_ops = xt_hook_ops_alloc(&packet_mangler, iptable_mangle_hook);
119117
if (IS_ERR(mangle_ops)) {
118+
xt_unregister_template(&packet_mangler);
120119
ret = PTR_ERR(mangle_ops);
121120
return ret;
122121
}
123122

124123
ret = register_pernet_subsys(&iptable_mangle_net_ops);
125124
if (ret < 0) {
125+
xt_unregister_template(&packet_mangler);
126126
kfree(mangle_ops);
127127
return ret;
128128
}
129129

130-
ret = iptable_mangle_table_init(&init_net);
131-
if (ret) {
132-
unregister_pernet_subsys(&iptable_mangle_net_ops);
133-
kfree(mangle_ops);
134-
}
135-
136130
return ret;
137131
}
138132

139133
static void __exit iptable_mangle_fini(void)
140134
{
141135
unregister_pernet_subsys(&iptable_mangle_net_ops);
136+
xt_unregister_template(&packet_mangler);
142137
kfree(mangle_ops);
143138
}
144139

net/ipv4/netfilter/iptable_nat.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ struct iptable_nat_pernet {
1717
struct nf_hook_ops *nf_nat_ops;
1818
};
1919

20-
static int __net_init iptable_nat_table_init(struct net *net);
21-
2220
static unsigned int iptable_nat_net_id __read_mostly;
2321

2422
static const struct xt_table nf_nat_ipv4_table = {
@@ -29,7 +27,6 @@ static const struct xt_table nf_nat_ipv4_table = {
2927
(1 << NF_INET_LOCAL_IN),
3028
.me = THIS_MODULE,
3129
.af = NFPROTO_IPV4,
32-
.table_init = iptable_nat_table_init,
3330
};
3431

3532
static unsigned int iptable_nat_do_chain(void *priv,
@@ -113,7 +110,7 @@ static void ipt_nat_unregister_lookups(struct net *net)
113110
kfree(ops);
114111
}
115112

116-
static int __net_init iptable_nat_table_init(struct net *net)
113+
static int iptable_nat_table_init(struct net *net)
117114
{
118115
struct ipt_replace *repl;
119116
int ret;
@@ -155,20 +152,25 @@ static struct pernet_operations iptable_nat_net_ops = {
155152

156153
static int __init iptable_nat_init(void)
157154
{
158-
int ret = register_pernet_subsys(&iptable_nat_net_ops);
155+
int ret = xt_register_template(&nf_nat_ipv4_table,
156+
iptable_nat_table_init);
157+
158+
if (ret < 0)
159+
return ret;
159160

160-
if (ret)
161+
ret = register_pernet_subsys(&iptable_nat_net_ops);
162+
if (ret < 0) {
163+
xt_unregister_template(&nf_nat_ipv4_table);
161164
return ret;
165+
}
162166

163-
ret = iptable_nat_table_init(&init_net);
164-
if (ret)
165-
unregister_pernet_subsys(&iptable_nat_net_ops);
166167
return ret;
167168
}
168169

169170
static void __exit iptable_nat_exit(void)
170171
{
171172
unregister_pernet_subsys(&iptable_nat_net_ops);
173+
xt_unregister_template(&nf_nat_ipv4_table);
172174
}
173175

174176
module_init(iptable_nat_init);

net/ipv4/netfilter/iptable_raw.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212

1313
#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))
1414

15-
static int __net_init iptable_raw_table_init(struct net *net);
16-
1715
static bool raw_before_defrag __read_mostly;
1816
MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag");
1917
module_param(raw_before_defrag, bool, 0000);
@@ -24,7 +22,6 @@ static const struct xt_table packet_raw = {
2422
.me = THIS_MODULE,
2523
.af = NFPROTO_IPV4,
2624
.priority = NF_IP_PRI_RAW,
27-
.table_init = iptable_raw_table_init,
2825
};
2926

3027
static const struct xt_table packet_raw_before_defrag = {
@@ -33,7 +30,6 @@ static const struct xt_table packet_raw_before_defrag = {
3330
.me = THIS_MODULE,
3431
.af = NFPROTO_IPV4,
3532
.priority = NF_IP_PRI_RAW_BEFORE_DEFRAG,
36-
.table_init = iptable_raw_table_init,
3733
};
3834

3935
/* The work comes in here from netfilter.c. */
@@ -89,29 +85,32 @@ static int __init iptable_raw_init(void)
8985
pr_info("Enabling raw table before defrag\n");
9086
}
9187

88+
ret = xt_register_template(table,
89+
iptable_raw_table_init);
90+
if (ret < 0)
91+
return ret;
92+
9293
rawtable_ops = xt_hook_ops_alloc(table, iptable_raw_hook);
93-
if (IS_ERR(rawtable_ops))
94+
if (IS_ERR(rawtable_ops)) {
95+
xt_unregister_template(table);
9496
return PTR_ERR(rawtable_ops);
97+
}
9598

9699
ret = register_pernet_subsys(&iptable_raw_net_ops);
97100
if (ret < 0) {
101+
xt_unregister_template(table);
98102
kfree(rawtable_ops);
99103
return ret;
100104
}
101105

102-
ret = iptable_raw_table_init(&init_net);
103-
if (ret) {
104-
unregister_pernet_subsys(&iptable_raw_net_ops);
105-
kfree(rawtable_ops);
106-
}
107-
108106
return ret;
109107
}
110108

111109
static void __exit iptable_raw_fini(void)
112110
{
113111
unregister_pernet_subsys(&iptable_raw_net_ops);
114112
kfree(rawtable_ops);
113+
xt_unregister_template(&packet_raw);
115114
}
116115

117116
module_init(iptable_raw_init);

0 commit comments

Comments
 (0)