diff options
author | Patrick McHardy <kaber@trash.net> | 2008-06-17 18:51:47 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-17 18:51:47 -0400 |
commit | 68b80f11380889996aa7eadba29dbbb5c29a5864 (patch) | |
tree | e6425d1ee4d15713678e60cd03bd5f514385e6e5 /net/ipv4 | |
parent | 65c3e4715b1b934f8dcc002d9f46b4371ca7a9b1 (diff) |
netfilter: nf_nat: fix RCU races
Fix three ct_extend/NAT extension related races:
- When cleaning up the extension area and removing it from the bysource hash,
the nat->ct pointer must not be set to NULL since it may still be used in
a RCU read side
- When replacing a NAT extension area in the bysource hash, the nat->ct
pointer must be assigned before performing the replacement
- When reallocating extension storage in ct_extend, the old memory must
not be freed immediately since it may still be used by a RCU read side
Possibly fixes https://bugzilla.redhat.com/show_bug.cgi?id=449315
and/or http://bugzilla.kernel.org/show_bug.cgi?id=10875
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter/nf_nat_core.c | 3 |
1 files changed, 1 insertions, 2 deletions
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 04578593e100..d2a887fc8d9b 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
@@ -556,7 +556,6 @@ static void nf_nat_cleanup_conntrack(struct nf_conn *ct) | |||
556 | 556 | ||
557 | spin_lock_bh(&nf_nat_lock); | 557 | spin_lock_bh(&nf_nat_lock); |
558 | hlist_del_rcu(&nat->bysource); | 558 | hlist_del_rcu(&nat->bysource); |
559 | nat->ct = NULL; | ||
560 | spin_unlock_bh(&nf_nat_lock); | 559 | spin_unlock_bh(&nf_nat_lock); |
561 | } | 560 | } |
562 | 561 | ||
@@ -570,8 +569,8 @@ static void nf_nat_move_storage(void *new, void *old) | |||
570 | return; | 569 | return; |
571 | 570 | ||
572 | spin_lock_bh(&nf_nat_lock); | 571 | spin_lock_bh(&nf_nat_lock); |
573 | hlist_replace_rcu(&old_nat->bysource, &new_nat->bysource); | ||
574 | new_nat->ct = ct; | 572 | new_nat->ct = ct; |
573 | hlist_replace_rcu(&old_nat->bysource, &new_nat->bysource); | ||
575 | spin_unlock_bh(&nf_nat_lock); | 574 | spin_unlock_bh(&nf_nat_lock); |
576 | } | 575 | } |
577 | 576 | ||