diff options
Diffstat (limited to 'net/netfilter/nf_conntrack_timeout.c')
-rw-r--r-- | net/netfilter/nf_conntrack_timeout.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/net/netfilter/nf_conntrack_timeout.c b/net/netfilter/nf_conntrack_timeout.c index 0f828d05ea60..0cc584d3dbb1 100644 --- a/net/netfilter/nf_conntrack_timeout.c +++ b/net/netfilter/nf_conntrack_timeout.c @@ -22,15 +22,21 @@ #include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_timeout.h> -const struct nf_ct_timeout_hooks *nf_ct_timeout_hook __read_mostly; +const struct nf_ct_timeout_hooks __rcu *nf_ct_timeout_hook __read_mostly; EXPORT_SYMBOL_GPL(nf_ct_timeout_hook); static int untimeout(struct nf_conn *ct, void *timeout) { struct nf_conn_timeout *timeout_ext = nf_ct_timeout_find(ct); - if (timeout_ext && (!timeout || timeout_ext->timeout == timeout)) - RCU_INIT_POINTER(timeout_ext->timeout, NULL); + if (timeout_ext) { + const struct nf_ct_timeout *t; + + t = rcu_access_pointer(timeout_ext->timeout); + + if (!timeout || t == timeout) + RCU_INIT_POINTER(timeout_ext->timeout, NULL); + } /* We are not intended to delete this conntrack. */ return 0; @@ -127,7 +133,11 @@ void nf_ct_destroy_timeout(struct nf_conn *ct) if (h) { timeout_ext = nf_ct_timeout_find(ct); if (timeout_ext) { - h->timeout_put(timeout_ext->timeout); + struct nf_ct_timeout *t; + + t = rcu_dereference(timeout_ext->timeout); + if (t) + h->timeout_put(t); RCU_INIT_POINTER(timeout_ext->timeout, NULL); } } |