aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-02-12 14:13:43 -0500
committerDavid S. Miller <davem@davemloft.net>2007-02-12 14:13:43 -0500
commitc0e912d7ed8999f87fa7f084928aac1266e251f3 (patch)
treeec48a83001871b4e0db78ee9eab520a1fbb02e14 /net/netfilter
parentabbaccda4c364815b8b1a82c45a94f60760e13e1 (diff)
[NETFILTER]: nf_conntrack: fix invalid conntrack statistics RCU assumption
NF_CT_STAT_INC assumes rcu_read_lock in nf_hook_slow disables preemption as well, making it legal to use __get_cpu_var without disabling preemption manually. The assumption is not correct anymore with preemptable RCU, additionally we need to protect against softirqs when not holding nf_conntrack_lock. Add NF_CT_STAT_INC_ATOMIC macro, which disables local softirqs, and use where necessary. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/nf_conntrack_core.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 3deeb900263b..d59640e2377b 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -563,7 +563,7 @@ static int early_drop(struct list_head *chain)
563 if (del_timer(&ct->timeout)) { 563 if (del_timer(&ct->timeout)) {
564 death_by_timeout((unsigned long)ct); 564 death_by_timeout((unsigned long)ct);
565 dropped = 1; 565 dropped = 1;
566 NF_CT_STAT_INC(early_drop); 566 NF_CT_STAT_INC_ATOMIC(early_drop);
567 } 567 }
568 nf_ct_put(ct); 568 nf_ct_put(ct);
569 return dropped; 569 return dropped;
@@ -821,7 +821,7 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
821 821
822 /* Previously seen (loopback or untracked)? Ignore. */ 822 /* Previously seen (loopback or untracked)? Ignore. */
823 if ((*pskb)->nfct) { 823 if ((*pskb)->nfct) {
824 NF_CT_STAT_INC(ignore); 824 NF_CT_STAT_INC_ATOMIC(ignore);
825 return NF_ACCEPT; 825 return NF_ACCEPT;
826 } 826 }
827 827
@@ -840,8 +840,8 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
840 * core what to do with the packet. */ 840 * core what to do with the packet. */
841 if (l4proto->error != NULL && 841 if (l4proto->error != NULL &&
842 (ret = l4proto->error(*pskb, dataoff, &ctinfo, pf, hooknum)) <= 0) { 842 (ret = l4proto->error(*pskb, dataoff, &ctinfo, pf, hooknum)) <= 0) {
843 NF_CT_STAT_INC(error); 843 NF_CT_STAT_INC_ATOMIC(error);
844 NF_CT_STAT_INC(invalid); 844 NF_CT_STAT_INC_ATOMIC(invalid);
845 return -ret; 845 return -ret;
846 } 846 }
847 847
@@ -849,13 +849,13 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
849 &set_reply, &ctinfo); 849 &set_reply, &ctinfo);
850 if (!ct) { 850 if (!ct) {
851 /* Not valid part of a connection */ 851 /* Not valid part of a connection */
852 NF_CT_STAT_INC(invalid); 852 NF_CT_STAT_INC_ATOMIC(invalid);
853 return NF_ACCEPT; 853 return NF_ACCEPT;
854 } 854 }
855 855
856 if (IS_ERR(ct)) { 856 if (IS_ERR(ct)) {
857 /* Too stressed to deal. */ 857 /* Too stressed to deal. */
858 NF_CT_STAT_INC(drop); 858 NF_CT_STAT_INC_ATOMIC(drop);
859 return NF_DROP; 859 return NF_DROP;
860 } 860 }
861 861
@@ -868,7 +868,7 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
868 DEBUGP("nf_conntrack_in: Can't track with proto module\n"); 868 DEBUGP("nf_conntrack_in: Can't track with proto module\n");
869 nf_conntrack_put((*pskb)->nfct); 869 nf_conntrack_put((*pskb)->nfct);
870 (*pskb)->nfct = NULL; 870 (*pskb)->nfct = NULL;
871 NF_CT_STAT_INC(invalid); 871 NF_CT_STAT_INC_ATOMIC(invalid);
872 return -ret; 872 return -ret;
873 } 873 }
874 874