diff options
-rw-r--r-- | include/linux/netfilter_arp/arp_tables.h | 4 | ||||
-rw-r--r-- | include/linux/netfilter_ipv4/ip_tables.h | 5 | ||||
-rw-r--r-- | include/linux/netfilter_ipv6/ip6_tables.h | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/arp_tables.c | 22 | ||||
-rw-r--r-- | net/ipv4/netfilter/arptable_filter.c | 15 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_tables.c | 28 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_filter.c | 18 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_mangle.c | 18 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_raw.c | 18 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_rule.c | 16 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 24 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_filter.c | 17 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_mangle.c | 17 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_raw.c | 15 | ||||
-rw-r--r-- | net/netfilter/x_tables.c | 12 |
15 files changed, 134 insertions, 99 deletions
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index 53dd4df27aa1..f35486b3a7ca 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h | |||
@@ -271,8 +271,8 @@ struct arpt_error | |||
271 | xt_register_target(tgt); }) | 271 | xt_register_target(tgt); }) |
272 | #define arpt_unregister_target(tgt) xt_unregister_target(tgt) | 272 | #define arpt_unregister_target(tgt) xt_unregister_target(tgt) |
273 | 273 | ||
274 | extern int arpt_register_table(struct arpt_table *table, | 274 | extern struct arpt_table *arpt_register_table(struct arpt_table *table, |
275 | const struct arpt_replace *repl); | 275 | const struct arpt_replace *repl); |
276 | extern void arpt_unregister_table(struct arpt_table *table); | 276 | extern void arpt_unregister_table(struct arpt_table *table); |
277 | extern unsigned int arpt_do_table(struct sk_buff *skb, | 277 | extern unsigned int arpt_do_table(struct sk_buff *skb, |
278 | unsigned int hook, | 278 | unsigned int hook, |
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index 45fcad91e67b..bfc889f90276 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h | |||
@@ -244,8 +244,9 @@ ipt_get_target(struct ipt_entry *e) | |||
244 | #include <linux/init.h> | 244 | #include <linux/init.h> |
245 | extern void ipt_init(void) __init; | 245 | extern void ipt_init(void) __init; |
246 | 246 | ||
247 | extern int ipt_register_table(struct xt_table *table, | 247 | extern struct xt_table *ipt_register_table(struct net *net, |
248 | const struct ipt_replace *repl); | 248 | struct xt_table *table, |
249 | const struct ipt_replace *repl); | ||
249 | extern void ipt_unregister_table(struct xt_table *table); | 250 | extern void ipt_unregister_table(struct xt_table *table); |
250 | 251 | ||
251 | /* Standard entry. */ | 252 | /* Standard entry. */ |
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index 110801d699ee..f716c7506245 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h | |||
@@ -305,8 +305,8 @@ ip6t_get_target(struct ip6t_entry *e) | |||
305 | #include <linux/init.h> | 305 | #include <linux/init.h> |
306 | extern void ip6t_init(void) __init; | 306 | extern void ip6t_init(void) __init; |
307 | 307 | ||
308 | extern int ip6t_register_table(struct xt_table *table, | 308 | extern struct xt_table *ip6t_register_table(struct xt_table *table, |
309 | const struct ip6t_replace *repl); | 309 | const struct ip6t_replace *repl); |
310 | extern void ip6t_unregister_table(struct xt_table *table); | 310 | extern void ip6t_unregister_table(struct xt_table *table); |
311 | extern unsigned int ip6t_do_table(struct sk_buff *skb, | 311 | extern unsigned int ip6t_do_table(struct sk_buff *skb, |
312 | unsigned int hook, | 312 | unsigned int hook, |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 0da50a4a6578..3a5afb84e69f 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -1719,8 +1719,8 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len | |||
1719 | return ret; | 1719 | return ret; |
1720 | } | 1720 | } |
1721 | 1721 | ||
1722 | int arpt_register_table(struct arpt_table *table, | 1722 | struct arpt_table *arpt_register_table(struct arpt_table *table, |
1723 | const struct arpt_replace *repl) | 1723 | const struct arpt_replace *repl) |
1724 | { | 1724 | { |
1725 | int ret; | 1725 | int ret; |
1726 | struct xt_table_info *newinfo; | 1726 | struct xt_table_info *newinfo; |
@@ -1732,7 +1732,7 @@ int arpt_register_table(struct arpt_table *table, | |||
1732 | newinfo = xt_alloc_table_info(repl->size); | 1732 | newinfo = xt_alloc_table_info(repl->size); |
1733 | if (!newinfo) { | 1733 | if (!newinfo) { |
1734 | ret = -ENOMEM; | 1734 | ret = -ENOMEM; |
1735 | return ret; | 1735 | goto out; |
1736 | } | 1736 | } |
1737 | 1737 | ||
1738 | /* choose the copy on our node/cpu */ | 1738 | /* choose the copy on our node/cpu */ |
@@ -1746,18 +1746,20 @@ int arpt_register_table(struct arpt_table *table, | |||
1746 | repl->underflow); | 1746 | repl->underflow); |
1747 | 1747 | ||
1748 | duprintf("arpt_register_table: translate table gives %d\n", ret); | 1748 | duprintf("arpt_register_table: translate table gives %d\n", ret); |
1749 | if (ret != 0) { | 1749 | if (ret != 0) |
1750 | xt_free_table_info(newinfo); | 1750 | goto out_free; |
1751 | return ret; | ||
1752 | } | ||
1753 | 1751 | ||
1754 | new_table = xt_register_table(&init_net, table, &bootstrap, newinfo); | 1752 | new_table = xt_register_table(&init_net, table, &bootstrap, newinfo); |
1755 | if (IS_ERR(new_table)) { | 1753 | if (IS_ERR(new_table)) { |
1756 | xt_free_table_info(newinfo); | 1754 | ret = PTR_ERR(new_table); |
1757 | return PTR_ERR(new_table); | 1755 | goto out_free; |
1758 | } | 1756 | } |
1757 | return new_table; | ||
1759 | 1758 | ||
1760 | return 0; | 1759 | out_free: |
1760 | xt_free_table_info(newinfo); | ||
1761 | out: | ||
1762 | return ERR_PTR(ret); | ||
1761 | } | 1763 | } |
1762 | 1764 | ||
1763 | void arpt_unregister_table(struct arpt_table *table) | 1765 | void arpt_unregister_table(struct arpt_table *table) |
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index 7201511d54d2..b00321506a92 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c | |||
@@ -45,7 +45,7 @@ static struct | |||
45 | .term = ARPT_ERROR_INIT, | 45 | .term = ARPT_ERROR_INIT, |
46 | }; | 46 | }; |
47 | 47 | ||
48 | static struct arpt_table packet_filter = { | 48 | static struct arpt_table __packet_filter = { |
49 | .name = "filter", | 49 | .name = "filter", |
50 | .valid_hooks = FILTER_VALID_HOOKS, | 50 | .valid_hooks = FILTER_VALID_HOOKS, |
51 | .lock = RW_LOCK_UNLOCKED, | 51 | .lock = RW_LOCK_UNLOCKED, |
@@ -53,6 +53,7 @@ static struct arpt_table packet_filter = { | |||
53 | .me = THIS_MODULE, | 53 | .me = THIS_MODULE, |
54 | .af = NF_ARP, | 54 | .af = NF_ARP, |
55 | }; | 55 | }; |
56 | static struct arpt_table *packet_filter; | ||
56 | 57 | ||
57 | /* The work comes in here from netfilter.c */ | 58 | /* The work comes in here from netfilter.c */ |
58 | static unsigned int arpt_hook(unsigned int hook, | 59 | static unsigned int arpt_hook(unsigned int hook, |
@@ -61,7 +62,7 @@ static unsigned int arpt_hook(unsigned int hook, | |||
61 | const struct net_device *out, | 62 | const struct net_device *out, |
62 | int (*okfn)(struct sk_buff *)) | 63 | int (*okfn)(struct sk_buff *)) |
63 | { | 64 | { |
64 | return arpt_do_table(skb, hook, in, out, &packet_filter); | 65 | return arpt_do_table(skb, hook, in, out, packet_filter); |
65 | } | 66 | } |
66 | 67 | ||
67 | static struct nf_hook_ops arpt_ops[] __read_mostly = { | 68 | static struct nf_hook_ops arpt_ops[] __read_mostly = { |
@@ -90,9 +91,9 @@ static int __init arptable_filter_init(void) | |||
90 | int ret; | 91 | int ret; |
91 | 92 | ||
92 | /* Register table */ | 93 | /* Register table */ |
93 | ret = arpt_register_table(&packet_filter, &initial_table.repl); | 94 | packet_filter = arpt_register_table(&__packet_filter, &initial_table.repl); |
94 | if (ret < 0) | 95 | if (IS_ERR(packet_filter)) |
95 | return ret; | 96 | return PTR_ERR(packet_filter); |
96 | 97 | ||
97 | ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); | 98 | ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); |
98 | if (ret < 0) | 99 | if (ret < 0) |
@@ -100,14 +101,14 @@ static int __init arptable_filter_init(void) | |||
100 | return ret; | 101 | return ret; |
101 | 102 | ||
102 | cleanup_table: | 103 | cleanup_table: |
103 | arpt_unregister_table(&packet_filter); | 104 | arpt_unregister_table(packet_filter); |
104 | return ret; | 105 | return ret; |
105 | } | 106 | } |
106 | 107 | ||
107 | static void __exit arptable_filter_fini(void) | 108 | static void __exit arptable_filter_fini(void) |
108 | { | 109 | { |
109 | nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); | 110 | nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); |
110 | arpt_unregister_table(&packet_filter); | 111 | arpt_unregister_table(packet_filter); |
111 | } | 112 | } |
112 | 113 | ||
113 | module_init(arptable_filter_init); | 114 | module_init(arptable_filter_init); |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index bc22ea421a94..99dd62d93f4b 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -2048,7 +2048,8 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2048 | return ret; | 2048 | return ret; |
2049 | } | 2049 | } |
2050 | 2050 | ||
2051 | int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl) | 2051 | struct xt_table *ipt_register_table(struct net *net, struct xt_table *table, |
2052 | const struct ipt_replace *repl) | ||
2052 | { | 2053 | { |
2053 | int ret; | 2054 | int ret; |
2054 | struct xt_table_info *newinfo; | 2055 | struct xt_table_info *newinfo; |
@@ -2058,8 +2059,10 @@ int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl) | |||
2058 | struct xt_table *new_table; | 2059 | struct xt_table *new_table; |
2059 | 2060 | ||
2060 | newinfo = xt_alloc_table_info(repl->size); | 2061 | newinfo = xt_alloc_table_info(repl->size); |
2061 | if (!newinfo) | 2062 | if (!newinfo) { |
2062 | return -ENOMEM; | 2063 | ret = -ENOMEM; |
2064 | goto out; | ||
2065 | } | ||
2063 | 2066 | ||
2064 | /* choose the copy on our node/cpu, but dont care about preemption */ | 2067 | /* choose the copy on our node/cpu, but dont care about preemption */ |
2065 | loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; | 2068 | loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; |
@@ -2070,18 +2073,21 @@ int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl) | |||
2070 | repl->num_entries, | 2073 | repl->num_entries, |
2071 | repl->hook_entry, | 2074 | repl->hook_entry, |
2072 | repl->underflow); | 2075 | repl->underflow); |
2073 | if (ret != 0) { | 2076 | if (ret != 0) |
2074 | xt_free_table_info(newinfo); | 2077 | goto out_free; |
2075 | return ret; | ||
2076 | } | ||
2077 | 2078 | ||
2078 | new_table = xt_register_table(&init_net, table, &bootstrap, newinfo); | 2079 | new_table = xt_register_table(net, table, &bootstrap, newinfo); |
2079 | if (IS_ERR(new_table)) { | 2080 | if (IS_ERR(new_table)) { |
2080 | xt_free_table_info(newinfo); | 2081 | ret = PTR_ERR(new_table); |
2081 | return PTR_ERR(new_table); | 2082 | goto out_free; |
2082 | } | 2083 | } |
2083 | 2084 | ||
2084 | return 0; | 2085 | return new_table; |
2086 | |||
2087 | out_free: | ||
2088 | xt_free_table_info(newinfo); | ||
2089 | out: | ||
2090 | return ERR_PTR(ret); | ||
2085 | } | 2091 | } |
2086 | 2092 | ||
2087 | void ipt_unregister_table(struct xt_table *table) | 2093 | void ipt_unregister_table(struct xt_table *table) |
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 29bb4f9fbda0..3b43ca07a26c 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c | |||
@@ -53,13 +53,14 @@ static struct | |||
53 | .term = IPT_ERROR_INIT, /* ERROR */ | 53 | .term = IPT_ERROR_INIT, /* ERROR */ |
54 | }; | 54 | }; |
55 | 55 | ||
56 | static struct xt_table packet_filter = { | 56 | static struct xt_table __packet_filter = { |
57 | .name = "filter", | 57 | .name = "filter", |
58 | .valid_hooks = FILTER_VALID_HOOKS, | 58 | .valid_hooks = FILTER_VALID_HOOKS, |
59 | .lock = RW_LOCK_UNLOCKED, | 59 | .lock = RW_LOCK_UNLOCKED, |
60 | .me = THIS_MODULE, | 60 | .me = THIS_MODULE, |
61 | .af = AF_INET, | 61 | .af = AF_INET, |
62 | }; | 62 | }; |
63 | static struct xt_table *packet_filter; | ||
63 | 64 | ||
64 | /* The work comes in here from netfilter.c. */ | 65 | /* The work comes in here from netfilter.c. */ |
65 | static unsigned int | 66 | static unsigned int |
@@ -69,7 +70,7 @@ ipt_hook(unsigned int hook, | |||
69 | const struct net_device *out, | 70 | const struct net_device *out, |
70 | int (*okfn)(struct sk_buff *)) | 71 | int (*okfn)(struct sk_buff *)) |
71 | { | 72 | { |
72 | return ipt_do_table(skb, hook, in, out, &packet_filter); | 73 | return ipt_do_table(skb, hook, in, out, packet_filter); |
73 | } | 74 | } |
74 | 75 | ||
75 | static unsigned int | 76 | static unsigned int |
@@ -88,7 +89,7 @@ ipt_local_out_hook(unsigned int hook, | |||
88 | return NF_ACCEPT; | 89 | return NF_ACCEPT; |
89 | } | 90 | } |
90 | 91 | ||
91 | return ipt_do_table(skb, hook, in, out, &packet_filter); | 92 | return ipt_do_table(skb, hook, in, out, packet_filter); |
92 | } | 93 | } |
93 | 94 | ||
94 | static struct nf_hook_ops ipt_ops[] __read_mostly = { | 95 | static struct nf_hook_ops ipt_ops[] __read_mostly = { |
@@ -132,9 +133,10 @@ static int __init iptable_filter_init(void) | |||
132 | initial_table.entries[1].target.verdict = -forward - 1; | 133 | initial_table.entries[1].target.verdict = -forward - 1; |
133 | 134 | ||
134 | /* Register table */ | 135 | /* Register table */ |
135 | ret = ipt_register_table(&packet_filter, &initial_table.repl); | 136 | packet_filter = ipt_register_table(&init_net, &__packet_filter, |
136 | if (ret < 0) | 137 | &initial_table.repl); |
137 | return ret; | 138 | if (IS_ERR(packet_filter)) |
139 | return PTR_ERR(packet_filter); | ||
138 | 140 | ||
139 | /* Register hooks */ | 141 | /* Register hooks */ |
140 | ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | 142 | ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); |
@@ -144,14 +146,14 @@ static int __init iptable_filter_init(void) | |||
144 | return ret; | 146 | return ret; |
145 | 147 | ||
146 | cleanup_table: | 148 | cleanup_table: |
147 | ipt_unregister_table(&packet_filter); | 149 | ipt_unregister_table(packet_filter); |
148 | return ret; | 150 | return ret; |
149 | } | 151 | } |
150 | 152 | ||
151 | static void __exit iptable_filter_fini(void) | 153 | static void __exit iptable_filter_fini(void) |
152 | { | 154 | { |
153 | nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | 155 | nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); |
154 | ipt_unregister_table(&packet_filter); | 156 | ipt_unregister_table(packet_filter); |
155 | } | 157 | } |
156 | 158 | ||
157 | module_init(iptable_filter_init); | 159 | module_init(iptable_filter_init); |
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 5c4be202430c..292f2ed4416f 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c | |||
@@ -64,13 +64,14 @@ static struct | |||
64 | .term = IPT_ERROR_INIT, /* ERROR */ | 64 | .term = IPT_ERROR_INIT, /* ERROR */ |
65 | }; | 65 | }; |
66 | 66 | ||
67 | static struct xt_table packet_mangler = { | 67 | static struct xt_table __packet_mangler = { |
68 | .name = "mangle", | 68 | .name = "mangle", |
69 | .valid_hooks = MANGLE_VALID_HOOKS, | 69 | .valid_hooks = MANGLE_VALID_HOOKS, |
70 | .lock = RW_LOCK_UNLOCKED, | 70 | .lock = RW_LOCK_UNLOCKED, |
71 | .me = THIS_MODULE, | 71 | .me = THIS_MODULE, |
72 | .af = AF_INET, | 72 | .af = AF_INET, |
73 | }; | 73 | }; |
74 | static struct xt_table *packet_mangler; | ||
74 | 75 | ||
75 | /* The work comes in here from netfilter.c. */ | 76 | /* The work comes in here from netfilter.c. */ |
76 | static unsigned int | 77 | static unsigned int |
@@ -80,7 +81,7 @@ ipt_route_hook(unsigned int hook, | |||
80 | const struct net_device *out, | 81 | const struct net_device *out, |
81 | int (*okfn)(struct sk_buff *)) | 82 | int (*okfn)(struct sk_buff *)) |
82 | { | 83 | { |
83 | return ipt_do_table(skb, hook, in, out, &packet_mangler); | 84 | return ipt_do_table(skb, hook, in, out, packet_mangler); |
84 | } | 85 | } |
85 | 86 | ||
86 | static unsigned int | 87 | static unsigned int |
@@ -112,7 +113,7 @@ ipt_local_hook(unsigned int hook, | |||
112 | daddr = iph->daddr; | 113 | daddr = iph->daddr; |
113 | tos = iph->tos; | 114 | tos = iph->tos; |
114 | 115 | ||
115 | ret = ipt_do_table(skb, hook, in, out, &packet_mangler); | 116 | ret = ipt_do_table(skb, hook, in, out, packet_mangler); |
116 | /* Reroute for ANY change. */ | 117 | /* Reroute for ANY change. */ |
117 | if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) { | 118 | if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) { |
118 | iph = ip_hdr(skb); | 119 | iph = ip_hdr(skb); |
@@ -171,9 +172,10 @@ static int __init iptable_mangle_init(void) | |||
171 | int ret; | 172 | int ret; |
172 | 173 | ||
173 | /* Register table */ | 174 | /* Register table */ |
174 | ret = ipt_register_table(&packet_mangler, &initial_table.repl); | 175 | packet_mangler = ipt_register_table(&init_net, &__packet_mangler, |
175 | if (ret < 0) | 176 | &initial_table.repl); |
176 | return ret; | 177 | if (IS_ERR(packet_mangler)) |
178 | return PTR_ERR(packet_mangler); | ||
177 | 179 | ||
178 | /* Register hooks */ | 180 | /* Register hooks */ |
179 | ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | 181 | ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); |
@@ -183,14 +185,14 @@ static int __init iptable_mangle_init(void) | |||
183 | return ret; | 185 | return ret; |
184 | 186 | ||
185 | cleanup_table: | 187 | cleanup_table: |
186 | ipt_unregister_table(&packet_mangler); | 188 | ipt_unregister_table(packet_mangler); |
187 | return ret; | 189 | return ret; |
188 | } | 190 | } |
189 | 191 | ||
190 | static void __exit iptable_mangle_fini(void) | 192 | static void __exit iptable_mangle_fini(void) |
191 | { | 193 | { |
192 | nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | 194 | nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); |
193 | ipt_unregister_table(&packet_mangler); | 195 | ipt_unregister_table(packet_mangler); |
194 | } | 196 | } |
195 | 197 | ||
196 | module_init(iptable_mangle_init); | 198 | module_init(iptable_mangle_init); |
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index dc34aa274533..dab863dd0558 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c | |||
@@ -36,13 +36,14 @@ static struct | |||
36 | .term = IPT_ERROR_INIT, /* ERROR */ | 36 | .term = IPT_ERROR_INIT, /* ERROR */ |
37 | }; | 37 | }; |
38 | 38 | ||
39 | static struct xt_table packet_raw = { | 39 | static struct xt_table __packet_raw = { |
40 | .name = "raw", | 40 | .name = "raw", |
41 | .valid_hooks = RAW_VALID_HOOKS, | 41 | .valid_hooks = RAW_VALID_HOOKS, |
42 | .lock = RW_LOCK_UNLOCKED, | 42 | .lock = RW_LOCK_UNLOCKED, |
43 | .me = THIS_MODULE, | 43 | .me = THIS_MODULE, |
44 | .af = AF_INET, | 44 | .af = AF_INET, |
45 | }; | 45 | }; |
46 | static struct xt_table *packet_raw; | ||
46 | 47 | ||
47 | /* The work comes in here from netfilter.c. */ | 48 | /* The work comes in here from netfilter.c. */ |
48 | static unsigned int | 49 | static unsigned int |
@@ -52,7 +53,7 @@ ipt_hook(unsigned int hook, | |||
52 | const struct net_device *out, | 53 | const struct net_device *out, |
53 | int (*okfn)(struct sk_buff *)) | 54 | int (*okfn)(struct sk_buff *)) |
54 | { | 55 | { |
55 | return ipt_do_table(skb, hook, in, out, &packet_raw); | 56 | return ipt_do_table(skb, hook, in, out, packet_raw); |
56 | } | 57 | } |
57 | 58 | ||
58 | static unsigned int | 59 | static unsigned int |
@@ -70,7 +71,7 @@ ipt_local_hook(unsigned int hook, | |||
70 | "packet.\n"); | 71 | "packet.\n"); |
71 | return NF_ACCEPT; | 72 | return NF_ACCEPT; |
72 | } | 73 | } |
73 | return ipt_do_table(skb, hook, in, out, &packet_raw); | 74 | return ipt_do_table(skb, hook, in, out, packet_raw); |
74 | } | 75 | } |
75 | 76 | ||
76 | /* 'raw' is the very first table. */ | 77 | /* 'raw' is the very first table. */ |
@@ -96,9 +97,10 @@ static int __init iptable_raw_init(void) | |||
96 | int ret; | 97 | int ret; |
97 | 98 | ||
98 | /* Register table */ | 99 | /* Register table */ |
99 | ret = ipt_register_table(&packet_raw, &initial_table.repl); | 100 | packet_raw = ipt_register_table(&init_net, &__packet_raw, |
100 | if (ret < 0) | 101 | &initial_table.repl); |
101 | return ret; | 102 | if (IS_ERR(packet_raw)) |
103 | return PTR_ERR(packet_raw); | ||
102 | 104 | ||
103 | /* Register hooks */ | 105 | /* Register hooks */ |
104 | ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | 106 | ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); |
@@ -108,14 +110,14 @@ static int __init iptable_raw_init(void) | |||
108 | return ret; | 110 | return ret; |
109 | 111 | ||
110 | cleanup_table: | 112 | cleanup_table: |
111 | ipt_unregister_table(&packet_raw); | 113 | ipt_unregister_table(packet_raw); |
112 | return ret; | 114 | return ret; |
113 | } | 115 | } |
114 | 116 | ||
115 | static void __exit iptable_raw_fini(void) | 117 | static void __exit iptable_raw_fini(void) |
116 | { | 118 | { |
117 | nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); | 119 | nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); |
118 | ipt_unregister_table(&packet_raw); | 120 | ipt_unregister_table(packet_raw); |
119 | } | 121 | } |
120 | 122 | ||
121 | module_init(iptable_raw_init); | 123 | module_init(iptable_raw_init); |
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index 519182269e76..f8fda57ba20b 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c | |||
@@ -58,13 +58,14 @@ static struct | |||
58 | .term = IPT_ERROR_INIT, /* ERROR */ | 58 | .term = IPT_ERROR_INIT, /* ERROR */ |
59 | }; | 59 | }; |
60 | 60 | ||
61 | static struct xt_table nat_table = { | 61 | static struct xt_table __nat_table = { |
62 | .name = "nat", | 62 | .name = "nat", |
63 | .valid_hooks = NAT_VALID_HOOKS, | 63 | .valid_hooks = NAT_VALID_HOOKS, |
64 | .lock = RW_LOCK_UNLOCKED, | 64 | .lock = RW_LOCK_UNLOCKED, |
65 | .me = THIS_MODULE, | 65 | .me = THIS_MODULE, |
66 | .af = AF_INET, | 66 | .af = AF_INET, |
67 | }; | 67 | }; |
68 | static struct xt_table *nat_table; | ||
68 | 69 | ||
69 | /* Source NAT */ | 70 | /* Source NAT */ |
70 | static unsigned int ipt_snat_target(struct sk_buff *skb, | 71 | static unsigned int ipt_snat_target(struct sk_buff *skb, |
@@ -214,7 +215,7 @@ int nf_nat_rule_find(struct sk_buff *skb, | |||
214 | { | 215 | { |
215 | int ret; | 216 | int ret; |
216 | 217 | ||
217 | ret = ipt_do_table(skb, hooknum, in, out, &nat_table); | 218 | ret = ipt_do_table(skb, hooknum, in, out, nat_table); |
218 | 219 | ||
219 | if (ret == NF_ACCEPT) { | 220 | if (ret == NF_ACCEPT) { |
220 | if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) | 221 | if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) |
@@ -248,9 +249,10 @@ int __init nf_nat_rule_init(void) | |||
248 | { | 249 | { |
249 | int ret; | 250 | int ret; |
250 | 251 | ||
251 | ret = ipt_register_table(&nat_table, &nat_initial_table.repl); | 252 | nat_table = ipt_register_table(&init_net, &__nat_table, |
252 | if (ret != 0) | 253 | &nat_initial_table.repl); |
253 | return ret; | 254 | if (IS_ERR(nat_table)) |
255 | return PTR_ERR(nat_table); | ||
254 | ret = xt_register_target(&ipt_snat_reg); | 256 | ret = xt_register_target(&ipt_snat_reg); |
255 | if (ret != 0) | 257 | if (ret != 0) |
256 | goto unregister_table; | 258 | goto unregister_table; |
@@ -264,7 +266,7 @@ int __init nf_nat_rule_init(void) | |||
264 | unregister_snat: | 266 | unregister_snat: |
265 | xt_unregister_target(&ipt_snat_reg); | 267 | xt_unregister_target(&ipt_snat_reg); |
266 | unregister_table: | 268 | unregister_table: |
267 | ipt_unregister_table(&nat_table); | 269 | ipt_unregister_table(nat_table); |
268 | 270 | ||
269 | return ret; | 271 | return ret; |
270 | } | 272 | } |
@@ -273,5 +275,5 @@ void nf_nat_rule_cleanup(void) | |||
273 | { | 275 | { |
274 | xt_unregister_target(&ipt_dnat_reg); | 276 | xt_unregister_target(&ipt_dnat_reg); |
275 | xt_unregister_target(&ipt_snat_reg); | 277 | xt_unregister_target(&ipt_snat_reg); |
276 | ipt_unregister_table(&nat_table); | 278 | ipt_unregister_table(nat_table); |
277 | } | 279 | } |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 1aac3ef39414..b89f133f41d0 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -2074,7 +2074,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2074 | return ret; | 2074 | return ret; |
2075 | } | 2075 | } |
2076 | 2076 | ||
2077 | int ip6t_register_table(struct xt_table *table, const struct ip6t_replace *repl) | 2077 | struct xt_table *ip6t_register_table(struct xt_table *table, const struct ip6t_replace *repl) |
2078 | { | 2078 | { |
2079 | int ret; | 2079 | int ret; |
2080 | struct xt_table_info *newinfo; | 2080 | struct xt_table_info *newinfo; |
@@ -2084,8 +2084,10 @@ int ip6t_register_table(struct xt_table *table, const struct ip6t_replace *repl) | |||
2084 | struct xt_table *new_table; | 2084 | struct xt_table *new_table; |
2085 | 2085 | ||
2086 | newinfo = xt_alloc_table_info(repl->size); | 2086 | newinfo = xt_alloc_table_info(repl->size); |
2087 | if (!newinfo) | 2087 | if (!newinfo) { |
2088 | return -ENOMEM; | 2088 | ret = -ENOMEM; |
2089 | goto out; | ||
2090 | } | ||
2089 | 2091 | ||
2090 | /* choose the copy on our node/cpu, but dont care about preemption */ | 2092 | /* choose the copy on our node/cpu, but dont care about preemption */ |
2091 | loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; | 2093 | loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; |
@@ -2096,18 +2098,20 @@ int ip6t_register_table(struct xt_table *table, const struct ip6t_replace *repl) | |||
2096 | repl->num_entries, | 2098 | repl->num_entries, |
2097 | repl->hook_entry, | 2099 | repl->hook_entry, |
2098 | repl->underflow); | 2100 | repl->underflow); |
2099 | if (ret != 0) { | 2101 | if (ret != 0) |
2100 | xt_free_table_info(newinfo); | 2102 | goto out_free; |
2101 | return ret; | ||
2102 | } | ||
2103 | 2103 | ||
2104 | new_table = xt_register_table(&init_net, table, &bootstrap, newinfo); | 2104 | new_table = xt_register_table(&init_net, table, &bootstrap, newinfo); |
2105 | if (IS_ERR(new_table)) { | 2105 | if (IS_ERR(new_table)) { |
2106 | xt_free_table_info(newinfo); | 2106 | ret = PTR_ERR(new_table); |
2107 | return PTR_ERR(new_table); | 2107 | goto out_free; |
2108 | } | 2108 | } |
2109 | return new_table; | ||
2109 | 2110 | ||
2110 | return 0; | 2111 | out_free: |
2112 | xt_free_table_info(newinfo); | ||
2113 | out: | ||
2114 | return ERR_PTR(ret); | ||
2111 | } | 2115 | } |
2112 | 2116 | ||
2113 | void ip6t_unregister_table(struct xt_table *table) | 2117 | void ip6t_unregister_table(struct xt_table *table) |
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 87d38d08aad0..bffd67f32359 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -51,13 +51,14 @@ static struct | |||
51 | .term = IP6T_ERROR_INIT, /* ERROR */ | 51 | .term = IP6T_ERROR_INIT, /* ERROR */ |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static struct xt_table packet_filter = { | 54 | static struct xt_table __packet_filter = { |
55 | .name = "filter", | 55 | .name = "filter", |
56 | .valid_hooks = FILTER_VALID_HOOKS, | 56 | .valid_hooks = FILTER_VALID_HOOKS, |
57 | .lock = RW_LOCK_UNLOCKED, | 57 | .lock = RW_LOCK_UNLOCKED, |
58 | .me = THIS_MODULE, | 58 | .me = THIS_MODULE, |
59 | .af = AF_INET6, | 59 | .af = AF_INET6, |
60 | }; | 60 | }; |
61 | static struct xt_table *packet_filter; | ||
61 | 62 | ||
62 | /* The work comes in here from netfilter.c. */ | 63 | /* The work comes in here from netfilter.c. */ |
63 | static unsigned int | 64 | static unsigned int |
@@ -67,7 +68,7 @@ ip6t_hook(unsigned int hook, | |||
67 | const struct net_device *out, | 68 | const struct net_device *out, |
68 | int (*okfn)(struct sk_buff *)) | 69 | int (*okfn)(struct sk_buff *)) |
69 | { | 70 | { |
70 | return ip6t_do_table(skb, hook, in, out, &packet_filter); | 71 | return ip6t_do_table(skb, hook, in, out, packet_filter); |
71 | } | 72 | } |
72 | 73 | ||
73 | static unsigned int | 74 | static unsigned int |
@@ -87,7 +88,7 @@ ip6t_local_out_hook(unsigned int hook, | |||
87 | } | 88 | } |
88 | #endif | 89 | #endif |
89 | 90 | ||
90 | return ip6t_do_table(skb, hook, in, out, &packet_filter); | 91 | return ip6t_do_table(skb, hook, in, out, packet_filter); |
91 | } | 92 | } |
92 | 93 | ||
93 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { | 94 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { |
@@ -131,9 +132,9 @@ static int __init ip6table_filter_init(void) | |||
131 | initial_table.entries[1].target.verdict = -forward - 1; | 132 | initial_table.entries[1].target.verdict = -forward - 1; |
132 | 133 | ||
133 | /* Register table */ | 134 | /* Register table */ |
134 | ret = ip6t_register_table(&packet_filter, &initial_table.repl); | 135 | packet_filter = ip6t_register_table(&__packet_filter, &initial_table.repl); |
135 | if (ret < 0) | 136 | if (IS_ERR(packet_filter)) |
136 | return ret; | 137 | return PTR_ERR(packet_filter); |
137 | 138 | ||
138 | /* Register hooks */ | 139 | /* Register hooks */ |
139 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 140 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
@@ -143,14 +144,14 @@ static int __init ip6table_filter_init(void) | |||
143 | return ret; | 144 | return ret; |
144 | 145 | ||
145 | cleanup_table: | 146 | cleanup_table: |
146 | ip6t_unregister_table(&packet_filter); | 147 | ip6t_unregister_table(packet_filter); |
147 | return ret; | 148 | return ret; |
148 | } | 149 | } |
149 | 150 | ||
150 | static void __exit ip6table_filter_fini(void) | 151 | static void __exit ip6table_filter_fini(void) |
151 | { | 152 | { |
152 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 153 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
153 | ip6t_unregister_table(&packet_filter); | 154 | ip6t_unregister_table(packet_filter); |
154 | } | 155 | } |
155 | 156 | ||
156 | module_init(ip6table_filter_init); | 157 | module_init(ip6table_filter_init); |
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index d6082600bc5d..63d334df3b40 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -57,13 +57,14 @@ static struct | |||
57 | .term = IP6T_ERROR_INIT, /* ERROR */ | 57 | .term = IP6T_ERROR_INIT, /* ERROR */ |
58 | }; | 58 | }; |
59 | 59 | ||
60 | static struct xt_table packet_mangler = { | 60 | static struct xt_table __packet_mangler = { |
61 | .name = "mangle", | 61 | .name = "mangle", |
62 | .valid_hooks = MANGLE_VALID_HOOKS, | 62 | .valid_hooks = MANGLE_VALID_HOOKS, |
63 | .lock = RW_LOCK_UNLOCKED, | 63 | .lock = RW_LOCK_UNLOCKED, |
64 | .me = THIS_MODULE, | 64 | .me = THIS_MODULE, |
65 | .af = AF_INET6, | 65 | .af = AF_INET6, |
66 | }; | 66 | }; |
67 | static struct xt_table *packet_mangler; | ||
67 | 68 | ||
68 | /* The work comes in here from netfilter.c. */ | 69 | /* The work comes in here from netfilter.c. */ |
69 | static unsigned int | 70 | static unsigned int |
@@ -73,7 +74,7 @@ ip6t_route_hook(unsigned int hook, | |||
73 | const struct net_device *out, | 74 | const struct net_device *out, |
74 | int (*okfn)(struct sk_buff *)) | 75 | int (*okfn)(struct sk_buff *)) |
75 | { | 76 | { |
76 | return ip6t_do_table(skb, hook, in, out, &packet_mangler); | 77 | return ip6t_do_table(skb, hook, in, out, packet_mangler); |
77 | } | 78 | } |
78 | 79 | ||
79 | static unsigned int | 80 | static unsigned int |
@@ -108,7 +109,7 @@ ip6t_local_hook(unsigned int hook, | |||
108 | /* flowlabel and prio (includes version, which shouldn't change either */ | 109 | /* flowlabel and prio (includes version, which shouldn't change either */ |
109 | flowlabel = *((u_int32_t *)ipv6_hdr(skb)); | 110 | flowlabel = *((u_int32_t *)ipv6_hdr(skb)); |
110 | 111 | ||
111 | ret = ip6t_do_table(skb, hook, in, out, &packet_mangler); | 112 | ret = ip6t_do_table(skb, hook, in, out, packet_mangler); |
112 | 113 | ||
113 | if (ret != NF_DROP && ret != NF_STOLEN | 114 | if (ret != NF_DROP && ret != NF_STOLEN |
114 | && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) | 115 | && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) |
@@ -163,9 +164,9 @@ static int __init ip6table_mangle_init(void) | |||
163 | int ret; | 164 | int ret; |
164 | 165 | ||
165 | /* Register table */ | 166 | /* Register table */ |
166 | ret = ip6t_register_table(&packet_mangler, &initial_table.repl); | 167 | packet_mangler = ip6t_register_table(&__packet_mangler, &initial_table.repl); |
167 | if (ret < 0) | 168 | if (IS_ERR(packet_mangler)) |
168 | return ret; | 169 | return PTR_ERR(packet_mangler); |
169 | 170 | ||
170 | /* Register hooks */ | 171 | /* Register hooks */ |
171 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 172 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
@@ -175,14 +176,14 @@ static int __init ip6table_mangle_init(void) | |||
175 | return ret; | 176 | return ret; |
176 | 177 | ||
177 | cleanup_table: | 178 | cleanup_table: |
178 | ip6t_unregister_table(&packet_mangler); | 179 | ip6t_unregister_table(packet_mangler); |
179 | return ret; | 180 | return ret; |
180 | } | 181 | } |
181 | 182 | ||
182 | static void __exit ip6table_mangle_fini(void) | 183 | static void __exit ip6table_mangle_fini(void) |
183 | { | 184 | { |
184 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 185 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
185 | ip6t_unregister_table(&packet_mangler); | 186 | ip6t_unregister_table(packet_mangler); |
186 | } | 187 | } |
187 | 188 | ||
188 | module_init(ip6table_mangle_init); | 189 | module_init(ip6table_mangle_init); |
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index eccbaaa104af..7f55b236440e 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c | |||
@@ -35,13 +35,14 @@ static struct | |||
35 | .term = IP6T_ERROR_INIT, /* ERROR */ | 35 | .term = IP6T_ERROR_INIT, /* ERROR */ |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static struct xt_table packet_raw = { | 38 | static struct xt_table __packet_raw = { |
39 | .name = "raw", | 39 | .name = "raw", |
40 | .valid_hooks = RAW_VALID_HOOKS, | 40 | .valid_hooks = RAW_VALID_HOOKS, |
41 | .lock = RW_LOCK_UNLOCKED, | 41 | .lock = RW_LOCK_UNLOCKED, |
42 | .me = THIS_MODULE, | 42 | .me = THIS_MODULE, |
43 | .af = AF_INET6, | 43 | .af = AF_INET6, |
44 | }; | 44 | }; |
45 | static struct xt_table *packet_raw; | ||
45 | 46 | ||
46 | /* The work comes in here from netfilter.c. */ | 47 | /* The work comes in here from netfilter.c. */ |
47 | static unsigned int | 48 | static unsigned int |
@@ -51,7 +52,7 @@ ip6t_hook(unsigned int hook, | |||
51 | const struct net_device *out, | 52 | const struct net_device *out, |
52 | int (*okfn)(struct sk_buff *)) | 53 | int (*okfn)(struct sk_buff *)) |
53 | { | 54 | { |
54 | return ip6t_do_table(skb, hook, in, out, &packet_raw); | 55 | return ip6t_do_table(skb, hook, in, out, packet_raw); |
55 | } | 56 | } |
56 | 57 | ||
57 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { | 58 | static struct nf_hook_ops ip6t_ops[] __read_mostly = { |
@@ -76,9 +77,9 @@ static int __init ip6table_raw_init(void) | |||
76 | int ret; | 77 | int ret; |
77 | 78 | ||
78 | /* Register table */ | 79 | /* Register table */ |
79 | ret = ip6t_register_table(&packet_raw, &initial_table.repl); | 80 | packet_raw = ip6t_register_table(&__packet_raw, &initial_table.repl); |
80 | if (ret < 0) | 81 | if (IS_ERR(packet_raw)) |
81 | return ret; | 82 | return PTR_ERR(packet_raw); |
82 | 83 | ||
83 | /* Register hooks */ | 84 | /* Register hooks */ |
84 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 85 | ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
@@ -88,14 +89,14 @@ static int __init ip6table_raw_init(void) | |||
88 | return ret; | 89 | return ret; |
89 | 90 | ||
90 | cleanup_table: | 91 | cleanup_table: |
91 | ip6t_unregister_table(&packet_raw); | 92 | ip6t_unregister_table(packet_raw); |
92 | return ret; | 93 | return ret; |
93 | } | 94 | } |
94 | 95 | ||
95 | static void __exit ip6table_raw_fini(void) | 96 | static void __exit ip6table_raw_fini(void) |
96 | { | 97 | { |
97 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); | 98 | nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); |
98 | ip6t_unregister_table(&packet_raw); | 99 | ip6t_unregister_table(packet_raw); |
99 | } | 100 | } |
100 | 101 | ||
101 | module_init(ip6table_raw_init); | 102 | module_init(ip6table_raw_init); |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index d62f722ccccb..d7fbb1bb92ea 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -667,9 +667,16 @@ struct xt_table *xt_register_table(struct net *net, struct xt_table *table, | |||
667 | struct xt_table_info *private; | 667 | struct xt_table_info *private; |
668 | struct xt_table *t; | 668 | struct xt_table *t; |
669 | 669 | ||
670 | /* Don't add one object to multiple lists. */ | ||
671 | table = kmemdup(table, sizeof(struct xt_table), GFP_KERNEL); | ||
672 | if (!table) { | ||
673 | ret = -ENOMEM; | ||
674 | goto out; | ||
675 | } | ||
676 | |||
670 | ret = mutex_lock_interruptible(&xt[table->af].mutex); | 677 | ret = mutex_lock_interruptible(&xt[table->af].mutex); |
671 | if (ret != 0) | 678 | if (ret != 0) |
672 | goto out; | 679 | goto out_free; |
673 | 680 | ||
674 | /* Don't autoload: we'd eat our tail... */ | 681 | /* Don't autoload: we'd eat our tail... */ |
675 | list_for_each_entry(t, &net->xt.tables[table->af], list) { | 682 | list_for_each_entry(t, &net->xt.tables[table->af], list) { |
@@ -697,6 +704,8 @@ struct xt_table *xt_register_table(struct net *net, struct xt_table *table, | |||
697 | 704 | ||
698 | unlock: | 705 | unlock: |
699 | mutex_unlock(&xt[table->af].mutex); | 706 | mutex_unlock(&xt[table->af].mutex); |
707 | out_free: | ||
708 | kfree(table); | ||
700 | out: | 709 | out: |
701 | return ERR_PTR(ret); | 710 | return ERR_PTR(ret); |
702 | } | 711 | } |
@@ -710,6 +719,7 @@ void *xt_unregister_table(struct xt_table *table) | |||
710 | private = table->private; | 719 | private = table->private; |
711 | list_del(&table->list); | 720 | list_del(&table->list); |
712 | mutex_unlock(&xt[table->af].mutex); | 721 | mutex_unlock(&xt[table->af].mutex); |
722 | kfree(table); | ||
713 | 723 | ||
714 | return private; | 724 | return private; |
715 | } | 725 | } |