Commit:     5397e97d7533a03b28a7b8aeee648cbb36a8afc6
Parent:     c92b3a2f1f11655ecf6774b745017a414241d07c
Author:     Patrick McHardy <[EMAIL PROTECTED]>
AuthorDate: Sat May 19 14:23:52 2007 -0700
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Sat May 19 14:23:52 2007 -0700

    [NETFILTER]: nf_conntrack: fix use-after-free in helper destroy callback 
    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 <[EMAIL PROTECTED]>.
    Signed-off-by: Patrick McHardy <[EMAIL PROTECTED]>
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
 net/netfilter/nf_conntrack_core.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/nf_conntrack_core.c 
index e8b5c2d..483e927 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -298,7 +298,6 @@ static void
 destroy_conntrack(struct nf_conntrack *nfct)
        struct nf_conn *ct = (struct nf_conn *)nfct;
-       struct nf_conn_help *help = nfct_help(ct);
        struct nf_conntrack_l4proto *l4proto;
        typeof(nf_conntrack_destroyed) destroyed;
@@ -309,9 +308,6 @@ destroy_conntrack(struct nf_conntrack *nfct)
        nf_conntrack_event(IPCT_DESTROY, ct);
        set_bit(IPS_DYING_BIT, &ct->status);
-       if (help && help->helper && help->helper->destroy)
-               help->helper->destroy(ct);
        /* To make sure we don't get any weird locking issues here:
         * destroy_conntrack() MUST NOT be called with a write lock
         * to nf_conntrack_lock!!! -HW */
@@ -353,6 +349,10 @@ destroy_conntrack(struct nf_conntrack *nfct)
 static void death_by_timeout(unsigned long ul_conntrack)
        struct nf_conn *ct = (void *)ul_conntrack;
+       struct nf_conn_help *help = nfct_help(ct);
+       if (help && help->helper && help->helper->destroy)
+               help->helper->destroy(ct);
        /* Inside lock so preempt is disabled on module removal path.
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at

Reply via email to