diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2009-04-06 11:47:20 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2009-04-06 11:47:20 -0400 |
commit | 83731671d9e6878c0a05d309c68fb71c16d3235a (patch) | |
tree | e74df7769d32c4aad6a080796f32a7e09009a7ae | |
parent | 3ae16f13027c26cb4c227392116c2027524a6444 (diff) |
netfilter: ctnetlink: fix regression in expectation handling
This patch fixes a regression (introduced by myself in commit 19abb7b:
netfilter: ctnetlink: deliver events for conntracks changed from
userspace) that results in an expectation re-insertion since
__nf_ct_expect_check() may return 0 for expectation timer refreshing.
This patch also removes a unnecessary refcount bump that
pretended to avoid a possible race condition with event delivery
and expectation timers (as said, not needed since we hold a
reference to the object since until we finish the expectation
setup). This also merges nf_ct_expect_related_report() and
nf_ct_expect_related() which look basically the same.
Reported-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | include/net/netfilter/nf_conntrack_expect.h | 5 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_expect.c | 30 |
2 files changed, 10 insertions, 25 deletions
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index ab17a159ac66..a9652806d0df 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h | |||
@@ -99,9 +99,12 @@ void nf_ct_expect_init(struct nf_conntrack_expect *, unsigned int, u_int8_t, | |||
99 | const union nf_inet_addr *, | 99 | const union nf_inet_addr *, |
100 | u_int8_t, const __be16 *, const __be16 *); | 100 | u_int8_t, const __be16 *, const __be16 *); |
101 | void nf_ct_expect_put(struct nf_conntrack_expect *exp); | 101 | void nf_ct_expect_put(struct nf_conntrack_expect *exp); |
102 | int nf_ct_expect_related(struct nf_conntrack_expect *expect); | ||
103 | int nf_ct_expect_related_report(struct nf_conntrack_expect *expect, | 102 | int nf_ct_expect_related_report(struct nf_conntrack_expect *expect, |
104 | u32 pid, int report); | 103 | u32 pid, int report); |
104 | static inline int nf_ct_expect_related(struct nf_conntrack_expect *expect) | ||
105 | { | ||
106 | return nf_ct_expect_related_report(expect, 0, 0); | ||
107 | } | ||
105 | 108 | ||
106 | #endif /*_NF_CONNTRACK_EXPECT_H*/ | 109 | #endif /*_NF_CONNTRACK_EXPECT_H*/ |
107 | 110 | ||
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 3940f996a2e4..afde8f991646 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
@@ -372,7 +372,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) | |||
372 | struct net *net = nf_ct_exp_net(expect); | 372 | struct net *net = nf_ct_exp_net(expect); |
373 | struct hlist_node *n; | 373 | struct hlist_node *n; |
374 | unsigned int h; | 374 | unsigned int h; |
375 | int ret = 0; | 375 | int ret = 1; |
376 | 376 | ||
377 | if (!master_help->helper) { | 377 | if (!master_help->helper) { |
378 | ret = -ESHUTDOWN; | 378 | ret = -ESHUTDOWN; |
@@ -412,41 +412,23 @@ out: | |||
412 | return ret; | 412 | return ret; |
413 | } | 413 | } |
414 | 414 | ||
415 | int nf_ct_expect_related(struct nf_conntrack_expect *expect) | 415 | int nf_ct_expect_related_report(struct nf_conntrack_expect *expect, |
416 | u32 pid, int report) | ||
416 | { | 417 | { |
417 | int ret; | 418 | int ret; |
418 | 419 | ||
419 | spin_lock_bh(&nf_conntrack_lock); | 420 | spin_lock_bh(&nf_conntrack_lock); |
420 | ret = __nf_ct_expect_check(expect); | 421 | ret = __nf_ct_expect_check(expect); |
421 | if (ret < 0) | 422 | if (ret <= 0) |
422 | goto out; | 423 | goto out; |
423 | 424 | ||
425 | ret = 0; | ||
424 | nf_ct_expect_insert(expect); | 426 | nf_ct_expect_insert(expect); |
425 | atomic_inc(&expect->use); | ||
426 | spin_unlock_bh(&nf_conntrack_lock); | ||
427 | nf_ct_expect_event(IPEXP_NEW, expect); | ||
428 | nf_ct_expect_put(expect); | ||
429 | return ret; | ||
430 | out: | ||
431 | spin_unlock_bh(&nf_conntrack_lock); | 427 | spin_unlock_bh(&nf_conntrack_lock); |
428 | nf_ct_expect_event_report(IPEXP_NEW, expect, pid, report); | ||
432 | return ret; | 429 | return ret; |
433 | } | ||
434 | EXPORT_SYMBOL_GPL(nf_ct_expect_related); | ||
435 | |||
436 | int nf_ct_expect_related_report(struct nf_conntrack_expect *expect, | ||
437 | u32 pid, int report) | ||
438 | { | ||
439 | int ret; | ||
440 | |||
441 | spin_lock_bh(&nf_conntrack_lock); | ||
442 | ret = __nf_ct_expect_check(expect); | ||
443 | if (ret < 0) | ||
444 | goto out; | ||
445 | nf_ct_expect_insert(expect); | ||
446 | out: | 430 | out: |
447 | spin_unlock_bh(&nf_conntrack_lock); | 431 | spin_unlock_bh(&nf_conntrack_lock); |
448 | if (ret == 0) | ||
449 | nf_ct_expect_event_report(IPEXP_NEW, expect, pid, report); | ||
450 | return ret; | 432 | return ret; |
451 | } | 433 | } |
452 | EXPORT_SYMBOL_GPL(nf_ct_expect_related_report); | 434 | EXPORT_SYMBOL_GPL(nf_ct_expect_related_report); |