diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2012-03-15 22:00:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-03-17 04:47:08 -0400 |
commit | a16a1647fa6b6783c2e91623e72e86f0c2adac5e (patch) | |
tree | 949b73345b860aec586d67243eab4a9944a158ad /net | |
parent | c577923756b7fe9071f28a76b66b83b306d1d001 (diff) |
netfilter: ctnetlink: fix race between delete and timeout expiration
Kerin Millar reported hardlockups while running `conntrackd -c'
in a busy firewall. That system (with several processors) was
acting as backup in a primary-backup setup.
After several tries, I found a race condition between the deletion
operation of ctnetlink and timeout expiration. This patch fixes
this problem.
Tested-by: Kerin Millar <kerframil@gmail.com>
Reported-by: Kerin Millar <kerframil@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 10687692831e..b49da6c925b3 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -943,20 +943,21 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
943 | } | 943 | } |
944 | } | 944 | } |
945 | 945 | ||
946 | if (nf_conntrack_event_report(IPCT_DESTROY, ct, | 946 | if (del_timer(&ct->timeout)) { |
947 | NETLINK_CB(skb).pid, | 947 | if (nf_conntrack_event_report(IPCT_DESTROY, ct, |
948 | nlmsg_report(nlh)) < 0) { | 948 | NETLINK_CB(skb).pid, |
949 | nlmsg_report(nlh)) < 0) { | ||
950 | nf_ct_delete_from_lists(ct); | ||
951 | /* we failed to report the event, try later */ | ||
952 | nf_ct_insert_dying_list(ct); | ||
953 | nf_ct_put(ct); | ||
954 | return 0; | ||
955 | } | ||
956 | /* death_by_timeout would report the event again */ | ||
957 | set_bit(IPS_DYING_BIT, &ct->status); | ||
949 | nf_ct_delete_from_lists(ct); | 958 | nf_ct_delete_from_lists(ct); |
950 | /* we failed to report the event, try later */ | ||
951 | nf_ct_insert_dying_list(ct); | ||
952 | nf_ct_put(ct); | 959 | nf_ct_put(ct); |
953 | return 0; | ||
954 | } | 960 | } |
955 | |||
956 | /* death_by_timeout would report the event again */ | ||
957 | set_bit(IPS_DYING_BIT, &ct->status); | ||
958 | |||
959 | nf_ct_kill(ct); | ||
960 | nf_ct_put(ct); | 961 | nf_ct_put(ct); |
961 | 962 | ||
962 | return 0; | 963 | return 0; |