summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorHarald Welte <laforge@netfilter.org>2005-09-22 23:46:57 -0700
committerDavid S. Miller <davem@davemloft.net>2005-09-22 23:46:57 -0700
commit1dfbab59498d6f227c91988bab6c71af049a5333 (patch)
tree6b20409a232ebe8c37f16d06b3fbcde6bec8f328 /include/linux
parenta82b748930fce0dab22c64075c38c830ae116904 (diff)
[NETFILTER] Fix conntrack event cache deadlock/oops
This patch fixes a number of bugs. It cannot be reasonably split up in multiple fixes, since all bugs interact with each other and affect the same function: Bug #1: The event cache code cannot be called while a lock is held. Therefore, the call to ip_conntrack_event_cache() within ip_ct_refresh_acct() needs to be moved outside of the locked section. This fixes a number of 2.6.14-rcX oops and deadlock reports. Bug #2: We used to call ct_add_counters() for unconfirmed connections without holding a lock. Since the add operations are not atomic, we could race with another CPU. Bug #3: ip_ct_refresh_acct() lost REFRESH events in some cases where refresh (and the corresponding event) are desired, but no accounting shall be performed. Both, evenst and accounting implicitly depended on the skb parameter bein non-null. We now re-introduce a non-accounting "ip_ct_refresh()" variant to explicitly state the desired behaviour. Signed-off-by: Harald Welte <laforge@netfilter.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack.h25
1 files changed, 21 insertions, 4 deletions
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index bace72a76cc4..4ced38736813 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -332,11 +332,28 @@ extern void need_ip_conntrack(void);
extern int invert_tuplepr(struct ip_conntrack_tuple *inverse,
const struct ip_conntrack_tuple *orig);
+extern void __ip_ct_refresh_acct(struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ const struct sk_buff *skb,
+ unsigned long extra_jiffies,
+ int do_acct);
+
+/* Refresh conntrack for this many jiffies and do accounting */
+static inline void ip_ct_refresh_acct(struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ const struct sk_buff *skb,
+ unsigned long extra_jiffies)
+{
+ __ip_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies, 1);
+}
+
/* Refresh conntrack for this many jiffies */
-extern void ip_ct_refresh_acct(struct ip_conntrack *ct,
- enum ip_conntrack_info ctinfo,
- const struct sk_buff *skb,
- unsigned long extra_jiffies);
+static inline void ip_ct_refresh(struct ip_conntrack *ct,
+ const struct sk_buff *skb,
+ unsigned long extra_jiffies)
+{
+ __ip_ct_refresh_acct(ct, 0, skb, extra_jiffies, 0);
+}
/* These are for NAT. Icky. */
/* Update TCP window tracking data when NAT mangles the packet */