aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-02-12 14:09:19 -0500
committerDavid S. Miller <davem@davemloft.net>2007-02-12 14:09:19 -0500
commitc3a47ab3e5ad62601449e4e5401352271b777e28 (patch)
tree3b3f6810796367efa5f76209aed12bec6c6a8b17 /net
parentebaf0c6032f525ddb0158fb59848d41899dce8cd (diff)
[NETFILTER]: Properly use RCU in nf_ct_attach
Use rcu_assign_pointer/rcu_dereference for ip_ct_attach pointer instead of self-made RCU and use rcu_read_lock to make sure the conntrack module doesn't disappear below us while calling it, since this function can be called from outside the netfilter hooks. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c4
-rw-r--r--net/netfilter/core.c9
-rw-r--r--net/netfilter/nf_conntrack_core.c4
3 files changed, 10 insertions, 7 deletions
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 04e466d53c0b..508e6007a191 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -1354,7 +1354,7 @@ static void free_conntrack_hash(struct list_head *hash, int vmalloced,int size)
1354 supposed to kill the mall. */ 1354 supposed to kill the mall. */
1355void ip_conntrack_cleanup(void) 1355void ip_conntrack_cleanup(void)
1356{ 1356{
1357 ip_ct_attach = NULL; 1357 rcu_assign_pointer(ip_ct_attach, NULL);
1358 1358
1359 /* This makes sure all current packets have passed through 1359 /* This makes sure all current packets have passed through
1360 netfilter framework. Roll on, two-stage module 1360 netfilter framework. Roll on, two-stage module
@@ -1515,7 +1515,7 @@ int __init ip_conntrack_init(void)
1515 write_unlock_bh(&ip_conntrack_lock); 1515 write_unlock_bh(&ip_conntrack_lock);
1516 1516
1517 /* For use by ipt_REJECT */ 1517 /* For use by ipt_REJECT */
1518 ip_ct_attach = ip_conntrack_attach; 1518 rcu_assign_pointer(ip_ct_attach, ip_conntrack_attach);
1519 1519
1520 /* Set up fake conntrack: 1520 /* Set up fake conntrack:
1521 - to never be deleted, not in any hashes */ 1521 - to never be deleted, not in any hashes */
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 291b8c6862f1..ad24d0c005e2 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -248,9 +248,12 @@ void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
248{ 248{
249 void (*attach)(struct sk_buff *, struct sk_buff *); 249 void (*attach)(struct sk_buff *, struct sk_buff *);
250 250
251 if (skb->nfct && (attach = ip_ct_attach) != NULL) { 251 if (skb->nfct) {
252 mb(); /* Just to be sure: must be read before executing this */ 252 rcu_read_lock();
253 attach(new, skb); 253 attach = rcu_dereference(ip_ct_attach);
254 if (attach)
255 attach(new, skb);
256 rcu_read_unlock();
254 } 257 }
255} 258}
256EXPORT_SYMBOL(nf_ct_attach); 259EXPORT_SYMBOL(nf_ct_attach);
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 9b02ec4012fb..59bcab1d1084 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1105,7 +1105,7 @@ void nf_conntrack_cleanup(void)
1105{ 1105{
1106 int i; 1106 int i;
1107 1107
1108 ip_ct_attach = NULL; 1108 rcu_assign_pointer(ip_ct_attach, NULL);
1109 1109
1110 /* This makes sure all current packets have passed through 1110 /* This makes sure all current packets have passed through
1111 netfilter framework. Roll on, two-stage module 1111 netfilter framework. Roll on, two-stage module
@@ -1273,7 +1273,7 @@ int __init nf_conntrack_init(void)
1273 write_unlock_bh(&nf_conntrack_lock); 1273 write_unlock_bh(&nf_conntrack_lock);
1274 1274
1275 /* For use by REJECT target */ 1275 /* For use by REJECT target */
1276 ip_ct_attach = __nf_conntrack_attach; 1276 rcu_assign_pointer(ip_ct_attach, __nf_conntrack_attach);
1277 1277
1278 /* Set up fake conntrack: 1278 /* Set up fake conntrack:
1279 - to never be deleted, not in any hashes */ 1279 - to never be deleted, not in any hashes */