aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-05-19 17:23:52 -0400
committerDavid S. Miller <davem@davemloft.net>2007-05-19 17:23:52 -0400
commit5397e97d7533a03b28a7b8aeee648cbb36a8afc6 (patch)
tree178b2db127eec358138a8312280a36de51dcf91f
parentc92b3a2f1f11655ecf6774b745017a414241d07c (diff)
[NETFILTER]: nf_conntrack: fix use-after-free in helper destroy callback invocation
When the helper module is removed for a master connection that has a fulfilled expectation, but has already timed out and got removed from the hash tables, nf_conntrack_helper_unregister can't find the master connection to unset the helper, causing a use-after-free when the expected connection is destroyed and releases the last reference to the master. The helper destroy callback was introduced for the PPtP helper to clean up expectations and expected connections when the master connection times out, but doing this from destroy_conntrack only works for unfulfilled expectations since expected connections hold a reference to the master, preventing its destruction. Move the destroy callback to the timeout function, which fixes both problems. Reported/tested by Gabor Burjan <buga@buvoshetes.hu>. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/netfilter/nf_conntrack_core.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index e8b5c2d7db62..483e927a9ca4 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -298,7 +298,6 @@ static void
298destroy_conntrack(struct nf_conntrack *nfct) 298destroy_conntrack(struct nf_conntrack *nfct)
299{ 299{
300 struct nf_conn *ct = (struct nf_conn *)nfct; 300 struct nf_conn *ct = (struct nf_conn *)nfct;
301 struct nf_conn_help *help = nfct_help(ct);
302 struct nf_conntrack_l4proto *l4proto; 301 struct nf_conntrack_l4proto *l4proto;
303 typeof(nf_conntrack_destroyed) destroyed; 302 typeof(nf_conntrack_destroyed) destroyed;
304 303
@@ -309,9 +308,6 @@ destroy_conntrack(struct nf_conntrack *nfct)
309 nf_conntrack_event(IPCT_DESTROY, ct); 308 nf_conntrack_event(IPCT_DESTROY, ct);
310 set_bit(IPS_DYING_BIT, &ct->status); 309 set_bit(IPS_DYING_BIT, &ct->status);
311 310
312 if (help && help->helper && help->helper->destroy)
313 help->helper->destroy(ct);
314
315 /* To make sure we don't get any weird locking issues here: 311 /* To make sure we don't get any weird locking issues here:
316 * destroy_conntrack() MUST NOT be called with a write lock 312 * destroy_conntrack() MUST NOT be called with a write lock
317 * to nf_conntrack_lock!!! -HW */ 313 * to nf_conntrack_lock!!! -HW */
@@ -353,6 +349,10 @@ destroy_conntrack(struct nf_conntrack *nfct)
353static void death_by_timeout(unsigned long ul_conntrack) 349static void death_by_timeout(unsigned long ul_conntrack)
354{ 350{
355 struct nf_conn *ct = (void *)ul_conntrack; 351 struct nf_conn *ct = (void *)ul_conntrack;
352 struct nf_conn_help *help = nfct_help(ct);
353
354 if (help && help->helper && help->helper->destroy)
355 help->helper->destroy(ct);
356 356
357 write_lock_bh(&nf_conntrack_lock); 357 write_lock_bh(&nf_conntrack_lock);
358 /* Inside lock so preempt is disabled on module removal path. 358 /* Inside lock so preempt is disabled on module removal path.