aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorPatrick McHarrdy <kaber@trash.net>2007-06-05 15:55:27 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-06-07 16:40:26 -0400
commit3c158f7f57601bc27eab82f0dc4fd3fad314d845 (patch)
tree03c8f9d7fa1e51d852ff6b90c35030491613df03 /net/ipv6
parent51055be81c3cb14d0165a7432b787098b817fd35 (diff)
[NETFILTER]: nf_conntrack: fix helper module unload races
When a helper module is unloaded all conntracks refering to it have their helper pointer NULLed out, leading to lots of races. In most places this can be fixed by proper use of RCU (they do already check for != NULL, but in a racy way), additionally nf_conntrack_expect_related needs to bail out when no helper is present. Also remove two paranoid BUG_ONs in nf_conntrack_proto_gre that are racy and not worth fixing. Signed-off-by: Patrick McHarrdy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index dc442fb791b0..1b1797f1f33d 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -160,6 +160,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
160{ 160{
161 struct nf_conn *ct; 161 struct nf_conn *ct;
162 struct nf_conn_help *help; 162 struct nf_conn_help *help;
163 struct nf_conntrack_helper *helper;
163 enum ip_conntrack_info ctinfo; 164 enum ip_conntrack_info ctinfo;
164 unsigned int ret, protoff; 165 unsigned int ret, protoff;
165 unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data; 166 unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data;
@@ -172,7 +173,11 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
172 goto out; 173 goto out;
173 174
174 help = nfct_help(ct); 175 help = nfct_help(ct);
175 if (!help || !help->helper) 176 if (!help)
177 goto out;
178 /* rcu_read_lock()ed by nf_hook_slow */
179 helper = rcu_dereference(help->helper);
180 if (!helper)
176 goto out; 181 goto out;
177 182
178 protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, 183 protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
@@ -182,7 +187,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
182 return NF_ACCEPT; 187 return NF_ACCEPT;
183 } 188 }
184 189
185 ret = help->helper->help(pskb, protoff, ct, ctinfo); 190 ret = helper->help(pskb, protoff, ct, ctinfo);
186 if (ret != NF_ACCEPT) 191 if (ret != NF_ACCEPT)
187 return ret; 192 return ret;
188out: 193out: