diff options
author | Patrick McHardy <kaber@trash.net> | 2007-12-18 01:42:51 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:59:06 -0500 |
commit | 051578ccbcdad3b24b621dfb652194e36759e8d5 (patch) | |
tree | d0afda1f43bd1e6de4d38e9efa4c498723e7f206 | |
parent | 1e796fda00f06bac584f0e4ad8750ab9430d79d3 (diff) |
[NETFILTER]: nf_nat: properly use RCU for ip_nat_decode_session
We need to use rcu_assign_pointer/rcu_dereference to avoid races.
Also remove an obsolete CONFIG_IP_NAT_NEEDED ifdef.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/netfilter.h | 11 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_standalone.c | 6 |
2 files changed, 11 insertions, 6 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 0947424d01d6..1a8487325a4f 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h | |||
@@ -256,11 +256,16 @@ extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); | |||
256 | static inline void | 256 | static inline void |
257 | nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family) | 257 | nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family) |
258 | { | 258 | { |
259 | #if defined(CONFIG_IP_NF_NAT_NEEDED) || defined(CONFIG_NF_NAT_NEEDED) | 259 | #ifdef CONFIG_NF_NAT_NEEDED |
260 | void (*decodefn)(struct sk_buff *, struct flowi *); | 260 | void (*decodefn)(struct sk_buff *, struct flowi *); |
261 | 261 | ||
262 | if (family == AF_INET && (decodefn = ip_nat_decode_session) != NULL) | 262 | if (family == AF_INET) { |
263 | decodefn(skb, fl); | 263 | rcu_read_lock(); |
264 | decodefn = rcu_dereference(ip_nat_decode_session); | ||
265 | if (decodefn) | ||
266 | decodefn(skb, fl); | ||
267 | rcu_read_unlock(); | ||
268 | } | ||
264 | #endif | 269 | #endif |
265 | } | 270 | } |
266 | 271 | ||
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index a2b02f01cc5c..99b2c788d5a8 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c | |||
@@ -332,7 +332,7 @@ static int __init nf_nat_standalone_init(void) | |||
332 | 332 | ||
333 | #ifdef CONFIG_XFRM | 333 | #ifdef CONFIG_XFRM |
334 | BUG_ON(ip_nat_decode_session != NULL); | 334 | BUG_ON(ip_nat_decode_session != NULL); |
335 | ip_nat_decode_session = nat_decode_session; | 335 | rcu_assign_pointer(ip_nat_decode_session, nat_decode_session); |
336 | #endif | 336 | #endif |
337 | ret = nf_nat_rule_init(); | 337 | ret = nf_nat_rule_init(); |
338 | if (ret < 0) { | 338 | if (ret < 0) { |
@@ -350,7 +350,7 @@ static int __init nf_nat_standalone_init(void) | |||
350 | nf_nat_rule_cleanup(); | 350 | nf_nat_rule_cleanup(); |
351 | cleanup_decode_session: | 351 | cleanup_decode_session: |
352 | #ifdef CONFIG_XFRM | 352 | #ifdef CONFIG_XFRM |
353 | ip_nat_decode_session = NULL; | 353 | rcu_assign_pointer(ip_nat_decode_session, NULL); |
354 | synchronize_net(); | 354 | synchronize_net(); |
355 | #endif | 355 | #endif |
356 | return ret; | 356 | return ret; |
@@ -361,7 +361,7 @@ static void __exit nf_nat_standalone_fini(void) | |||
361 | nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops)); | 361 | nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops)); |
362 | nf_nat_rule_cleanup(); | 362 | nf_nat_rule_cleanup(); |
363 | #ifdef CONFIG_XFRM | 363 | #ifdef CONFIG_XFRM |
364 | ip_nat_decode_session = NULL; | 364 | rcu_assign_pointer(ip_nat_decode_session, NULL); |
365 | synchronize_net(); | 365 | synchronize_net(); |
366 | #endif | 366 | #endif |
367 | /* Conntrack caches are unregistered in nf_conntrack_cleanup */ | 367 | /* Conntrack caches are unregistered in nf_conntrack_cleanup */ |